make tests green
This commit is contained in:
parent
3ba34f1762
commit
30823c1ce3
44 changed files with 415 additions and 403 deletions
|
|
@ -23,12 +23,14 @@ type
|
||||||
## in preventDeadlocks-mode guarantees re-entrancy.
|
## in preventDeadlocks-mode guarantees re-entrancy.
|
||||||
TCond* = TSysCond ## Nim condition variable
|
TCond* = TSysCond ## Nim condition variable
|
||||||
|
|
||||||
FLock* = object of TEffect ## effect that denotes that some lock operation
|
LockEffect* = object of RootEffect ## effect that denotes that some lock operation
|
||||||
## is performed
|
## is performed
|
||||||
FAquireLock* = object of FLock ## effect that denotes that some lock is
|
AquireEffect* = object of LockEffect ## effect that denotes that some lock is
|
||||||
## aquired
|
## aquired
|
||||||
FReleaseLock* = object of FLock ## effect that denotes that some lock is
|
ReleaseEffect* = object of LockEffect ## effect that denotes that some lock is
|
||||||
## released
|
## released
|
||||||
|
{.deprecated: [FLock: LockEffect, FAquireLock: AquireEffect,
|
||||||
|
FReleaseLock: ReleaseEffect].}
|
||||||
|
|
||||||
const
|
const
|
||||||
noDeadlocks = defined(preventDeadlocks)
|
noDeadlocks = defined(preventDeadlocks)
|
||||||
|
|
@ -58,7 +60,7 @@ proc deinitLock*(lock: var TLock) {.inline.} =
|
||||||
## Frees the resources associated with the lock.
|
## Frees the resources associated with the lock.
|
||||||
deinitSys(lock)
|
deinitSys(lock)
|
||||||
|
|
||||||
proc tryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} =
|
proc tryAcquire*(lock: var TLock): bool {.tags: [AquireEffect].} =
|
||||||
## Tries to acquire the given lock. Returns `true` on success.
|
## Tries to acquire the given lock. Returns `true` on success.
|
||||||
result = tryAcquireSys(lock)
|
result = tryAcquireSys(lock)
|
||||||
when noDeadlocks:
|
when noDeadlocks:
|
||||||
|
|
@ -90,7 +92,7 @@ proc tryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} =
|
||||||
inc(locksLen)
|
inc(locksLen)
|
||||||
assert orderedLocks()
|
assert orderedLocks()
|
||||||
|
|
||||||
proc acquire*(lock: var TLock) {.tags: [FAquireLock].} =
|
proc acquire*(lock: var TLock) {.tags: [AquireEffect].} =
|
||||||
## Acquires the given lock.
|
## Acquires the given lock.
|
||||||
when nodeadlocks:
|
when nodeadlocks:
|
||||||
var p = addr(lock)
|
var p = addr(lock)
|
||||||
|
|
@ -135,7 +137,7 @@ proc acquire*(lock: var TLock) {.tags: [FAquireLock].} =
|
||||||
else:
|
else:
|
||||||
acquireSys(lock)
|
acquireSys(lock)
|
||||||
|
|
||||||
proc release*(lock: var TLock) {.tags: [FReleaseLock].} =
|
proc release*(lock: var TLock) {.tags: [ReleaseEffect].} =
|
||||||
## Releases the given lock.
|
## Releases the given lock.
|
||||||
when nodeadlocks:
|
when nodeadlocks:
|
||||||
var p = addr(lock)
|
var p = addr(lock)
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ proc newGenTable*[T](mode: TGenTableMode): PGenTable[T] =
|
||||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||||
result = ((5 * h) + 1) and maxHash
|
result = ((5 * h) + 1) and maxHash
|
||||||
|
|
||||||
proc RawGet[T](tbl: PGenTable[T], key: string): int =
|
proc rawGet[T](tbl: PGenTable[T], key: string): int =
|
||||||
var h: THash
|
var h: THash
|
||||||
h = myhash(tbl, key) and high(tbl.data) # start with real hash value
|
h = myhash(tbl, key) and high(tbl.data) # start with real hash value
|
||||||
while not isNil(tbl.data[h].key):
|
while not isNil(tbl.data[h].key):
|
||||||
|
|
@ -83,7 +83,7 @@ proc RawGet[T](tbl: PGenTable[T], key: string): int =
|
||||||
h = nextTry(h, high(tbl.data))
|
h = nextTry(h, high(tbl.data))
|
||||||
result = - 1
|
result = - 1
|
||||||
|
|
||||||
proc RawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T],
|
proc rawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T],
|
||||||
key: string, val: T) =
|
key: string, val: T) =
|
||||||
var h: THash
|
var h: THash
|
||||||
h = myhash(tbl, key) and high(data)
|
h = myhash(tbl, key) and high(data)
|
||||||
|
|
@ -92,12 +92,12 @@ proc RawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T],
|
||||||
data[h].key = key
|
data[h].key = key
|
||||||
data[h].val = val
|
data[h].val = val
|
||||||
|
|
||||||
proc Enlarge[T](tbl: PGenTable[T]) =
|
proc enlarge[T](tbl: PGenTable[T]) =
|
||||||
var n: TGenKeyValuePairSeq[T]
|
var n: TGenKeyValuePairSeq[T]
|
||||||
newSeq(n, len(tbl.data) * growthFactor)
|
newSeq(n, len(tbl.data) * growthFactor)
|
||||||
for i in countup(0, high(tbl.data)):
|
for i in countup(0, high(tbl.data)):
|
||||||
if not isNil(tbl.data[i].key):
|
if not isNil(tbl.data[i].key):
|
||||||
RawInsert[T](tbl, n, tbl.data[i].key, tbl.data[i].val)
|
rawInsert[T](tbl, n, tbl.data[i].key, tbl.data[i].val)
|
||||||
swap(tbl.data, n)
|
swap(tbl.data, n)
|
||||||
|
|
||||||
proc hasKey*[T](tbl: PGenTable[T], key: string): bool =
|
proc hasKey*[T](tbl: PGenTable[T], key: string): bool =
|
||||||
|
|
@ -108,17 +108,17 @@ proc `[]`*[T](tbl: PGenTable[T], key: string): T =
|
||||||
## retrieves the value at ``tbl[key]``. If `key` is not in `tbl`,
|
## retrieves the value at ``tbl[key]``. If `key` is not in `tbl`,
|
||||||
## default(T) is returned and no exception is raised. One can check
|
## default(T) is returned and no exception is raised. One can check
|
||||||
## with ``hasKey`` whether the key exists.
|
## with ``hasKey`` whether the key exists.
|
||||||
var index = RawGet(tbl, key)
|
var index = rawGet(tbl, key)
|
||||||
if index >= 0: result = tbl.data[index].val
|
if index >= 0: result = tbl.data[index].val
|
||||||
|
|
||||||
proc `[]=`*[T](tbl: PGenTable[T], key: string, val: T) =
|
proc `[]=`*[T](tbl: PGenTable[T], key: string, val: T) =
|
||||||
## puts a (key, value)-pair into `tbl`.
|
## puts a (key, value)-pair into `tbl`.
|
||||||
var index = RawGet(tbl, key)
|
var index = rawGet(tbl, key)
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
tbl.data[index].val = val
|
tbl.data[index].val = val
|
||||||
else:
|
else:
|
||||||
if mustRehash(len(tbl.data), tbl.counter): Enlarge(tbl)
|
if mustRehash(len(tbl.data), tbl.counter): enlarge(tbl)
|
||||||
RawInsert(tbl, tbl.data, key, val)
|
rawInsert(tbl, tbl.data, key, val)
|
||||||
inc(tbl.counter)
|
inc(tbl.counter)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -422,7 +422,7 @@ proc toHtmlTag(s: string): THtmlTag =
|
||||||
of "wbr": tagWbr
|
of "wbr": tagWbr
|
||||||
else: tagUnknown
|
else: tagUnknown
|
||||||
|
|
||||||
proc htmlTag*(n: PXmlNode): THtmlTag =
|
proc htmlTag*(n: XmlNode): THtmlTag =
|
||||||
## gets `n`'s tag as a ``THtmlTag``.
|
## gets `n`'s tag as a ``THtmlTag``.
|
||||||
if n.clientData == 0:
|
if n.clientData == 0:
|
||||||
n.clientData = toHtmlTag(n.tag).ord
|
n.clientData = toHtmlTag(n.tag).ord
|
||||||
|
|
@ -438,24 +438,24 @@ proc entityToUtf8*(entity: string): string =
|
||||||
## converts an HTML entity name like ``Ü`` to its UTF-8 equivalent.
|
## converts an HTML entity name like ``Ü`` to its UTF-8 equivalent.
|
||||||
## "" is returned if the entity name is unknown. The HTML parser
|
## "" is returned if the entity name is unknown. The HTML parser
|
||||||
## already converts entities to UTF-8.
|
## already converts entities to UTF-8.
|
||||||
for name, val in items(entities):
|
for name, val in items(Entities):
|
||||||
if name == entity: return toUTF8(TRune(val))
|
if name == entity: return toUTF8(Rune(val))
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc addNode(father, son: PXmlNode) =
|
proc addNode(father, son: XmlNode) =
|
||||||
if son != nil: add(father, son)
|
if son != nil: add(father, son)
|
||||||
|
|
||||||
proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode
|
proc parse(x: var XmlParser, errors: var seq[string]): XmlNode
|
||||||
|
|
||||||
proc expected(x: var TXmlParser, n: PXmlNode): string =
|
proc expected(x: var XmlParser, n: XmlNode): string =
|
||||||
result = errorMsg(x, "</" & n.tag & "> expected")
|
result = errorMsg(x, "</" & n.tag & "> expected")
|
||||||
|
|
||||||
template elemName(x: expr): expr = rawData(x)
|
template elemName(x: expr): expr = rawData(x)
|
||||||
|
|
||||||
proc untilElementEnd(x: var TXmlParser, result: PXmlNode,
|
proc untilElementEnd(x: var XmlParser, result: XmlNode,
|
||||||
errors: var seq[string]) =
|
errors: var seq[string]) =
|
||||||
# we parsed e.g. ``<br>`` and don't really expect a ``</br>``:
|
# we parsed e.g. ``<br>`` and don't really expect a ``</br>``:
|
||||||
if result.htmlTag in singleTags:
|
if result.htmlTag in SingleTags:
|
||||||
if x.kind != xmlElementEnd or cmpIgnoreCase(x.elemName, result.tag) != 0:
|
if x.kind != xmlElementEnd or cmpIgnoreCase(x.elemName, result.tag) != 0:
|
||||||
return
|
return
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -496,7 +496,7 @@ proc untilElementEnd(x: var TXmlParser, result: PXmlNode,
|
||||||
else:
|
else:
|
||||||
result.addNode(parse(x, errors))
|
result.addNode(parse(x, errors))
|
||||||
|
|
||||||
proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
|
proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
|
||||||
case x.kind
|
case x.kind
|
||||||
of xmlComment:
|
of xmlComment:
|
||||||
result = newComment(x.rawData)
|
result = newComment(x.rawData)
|
||||||
|
|
@ -549,11 +549,11 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
|
||||||
next(x)
|
next(x)
|
||||||
of xmlEof: discard
|
of xmlEof: discard
|
||||||
|
|
||||||
proc parseHtml*(s: PStream, filename: string,
|
proc parseHtml*(s: Stream, filename: string,
|
||||||
errors: var seq[string]): PXmlNode =
|
errors: var seq[string]): XmlNode =
|
||||||
## parses the XML from stream `s` and returns a ``PXmlNode``. Every
|
## parses the XML from stream `s` and returns a ``PXmlNode``. Every
|
||||||
## occured parsing error is added to the `errors` sequence.
|
## occured parsing error is added to the `errors` sequence.
|
||||||
var x: TXmlParser
|
var x: XmlParser
|
||||||
open(x, s, filename, {reportComments, reportWhitespace})
|
open(x, s, filename, {reportComments, reportWhitespace})
|
||||||
next(x)
|
next(x)
|
||||||
# skip the DOCTYPE:
|
# skip the DOCTYPE:
|
||||||
|
|
@ -573,21 +573,21 @@ proc parseHtml*(s: PStream, filename: string,
|
||||||
if result.len == 1:
|
if result.len == 1:
|
||||||
result = result[0]
|
result = result[0]
|
||||||
|
|
||||||
proc parseHtml*(s: PStream): PXmlNode =
|
proc parseHtml*(s: Stream): XmlNode =
|
||||||
## parses the XTML from stream `s` and returns a ``PXmlNode``. All parsing
|
## parses the XTML from stream `s` and returns a ``PXmlNode``. All parsing
|
||||||
## errors are ignored.
|
## errors are ignored.
|
||||||
var errors: seq[string] = @[]
|
var errors: seq[string] = @[]
|
||||||
result = parseHtml(s, "unknown_html_doc", errors)
|
result = parseHtml(s, "unknown_html_doc", errors)
|
||||||
|
|
||||||
proc loadHtml*(path: string, errors: var seq[string]): PXmlNode =
|
proc loadHtml*(path: string, errors: var seq[string]): XmlNode =
|
||||||
## Loads and parses HTML from file specified by ``path``, and returns
|
## Loads and parses HTML from file specified by ``path``, and returns
|
||||||
## a ``PXmlNode``. Every occured parsing error is added to
|
## a ``PXmlNode``. Every occured parsing error is added to
|
||||||
## the `errors` sequence.
|
## the `errors` sequence.
|
||||||
var s = newFileStream(path, fmRead)
|
var s = newFileStream(path, fmRead)
|
||||||
if s == nil: raise newException(EIO, "Unable to read file: " & path)
|
if s == nil: raise newException(IOError, "Unable to read file: " & path)
|
||||||
result = parseHtml(s, path, errors)
|
result = parseHtml(s, path, errors)
|
||||||
|
|
||||||
proc loadHtml*(path: string): PXmlNode =
|
proc loadHtml*(path: string): XmlNode =
|
||||||
## Loads and parses HTML from file specified by ``path``, and returns
|
## Loads and parses HTML from file specified by ``path``, and returns
|
||||||
## a ``PXmlNode``. All parsing errors are ignored.
|
## a ``PXmlNode``. All parsing errors are ignored.
|
||||||
var errors: seq[string] = @[]
|
var errors: seq[string] = @[]
|
||||||
|
|
@ -600,7 +600,7 @@ when isMainModule:
|
||||||
var x = loadHtml(paramStr(1), errors)
|
var x = loadHtml(paramStr(1), errors)
|
||||||
for e in items(errors): echo e
|
for e in items(errors): echo e
|
||||||
|
|
||||||
var f: TFile
|
var f: File
|
||||||
if open(f, "test.txt", fmWrite):
|
if open(f, "test.txt", fmWrite):
|
||||||
f.write($x)
|
f.write($x)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
|
||||||
|
|
@ -276,14 +276,14 @@ proc parseComment(my: var XmlParser) =
|
||||||
my.bufpos = pos
|
my.bufpos = pos
|
||||||
my.kind = xmlComment
|
my.kind = xmlComment
|
||||||
|
|
||||||
proc parseWhitespace(my: var XmlParser, skip=False) =
|
proc parseWhitespace(my: var XmlParser, skip=false) =
|
||||||
var pos = my.bufpos
|
var pos = my.bufpos
|
||||||
var buf = my.buf
|
var buf = my.buf
|
||||||
while true:
|
while true:
|
||||||
case buf[pos]
|
case buf[pos]
|
||||||
of ' ', '\t':
|
of ' ', '\t':
|
||||||
if not skip: add(my.a, buf[pos])
|
if not skip: add(my.a, buf[pos])
|
||||||
Inc(pos)
|
inc(pos)
|
||||||
of '\c':
|
of '\c':
|
||||||
# the specification says that CR-LF, CR are to be transformed to LF
|
# the specification says that CR-LF, CR are to be transformed to LF
|
||||||
pos = lexbase.handleCR(my, pos)
|
pos = lexbase.handleCR(my, pos)
|
||||||
|
|
@ -304,7 +304,7 @@ const
|
||||||
proc parseName(my: var XmlParser, dest: var string) =
|
proc parseName(my: var XmlParser, dest: var string) =
|
||||||
var pos = my.bufpos
|
var pos = my.bufpos
|
||||||
var buf = my.buf
|
var buf = my.buf
|
||||||
if buf[pos] in nameStartChar:
|
if buf[pos] in NameStartChar:
|
||||||
while true:
|
while true:
|
||||||
add(dest, buf[pos])
|
add(dest, buf[pos])
|
||||||
inc(pos)
|
inc(pos)
|
||||||
|
|
@ -385,11 +385,11 @@ proc parsePI(my: var XmlParser) =
|
||||||
inc(pos)
|
inc(pos)
|
||||||
of '\c':
|
of '\c':
|
||||||
# the specification says that CR-LF, CR are to be transformed to LF
|
# the specification says that CR-LF, CR are to be transformed to LF
|
||||||
pos = lexbase.HandleCR(my, pos)
|
pos = lexbase.handleCR(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
add(my.b, '\L')
|
add(my.b, '\L')
|
||||||
of '\L':
|
of '\L':
|
||||||
pos = lexbase.HandleLF(my, pos)
|
pos = lexbase.handleLF(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
add(my.b, '\L')
|
add(my.b, '\L')
|
||||||
else:
|
else:
|
||||||
|
|
@ -420,11 +420,11 @@ proc parseSpecial(my: var XmlParser) =
|
||||||
inc(pos)
|
inc(pos)
|
||||||
add(my.a, '>')
|
add(my.a, '>')
|
||||||
of '\c':
|
of '\c':
|
||||||
pos = lexbase.HandleCR(my, pos)
|
pos = lexbase.handleCR(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
add(my.a, '\L')
|
add(my.a, '\L')
|
||||||
of '\L':
|
of '\L':
|
||||||
pos = lexbase.HandleLF(my, pos)
|
pos = lexbase.handleLF(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
add(my.a, '\L')
|
add(my.a, '\L')
|
||||||
else:
|
else:
|
||||||
|
|
@ -441,7 +441,7 @@ proc parseTag(my: var XmlParser) =
|
||||||
my.kind = xmlCharData
|
my.kind = xmlCharData
|
||||||
add(my.a, '<')
|
add(my.a, '<')
|
||||||
return
|
return
|
||||||
parseWhitespace(my, skip=True)
|
parseWhitespace(my, skip=true)
|
||||||
if my.buf[my.bufpos] in NameStartChar:
|
if my.buf[my.bufpos] in NameStartChar:
|
||||||
# an attribute follows:
|
# an attribute follows:
|
||||||
my.kind = xmlElementOpen
|
my.kind = xmlElementOpen
|
||||||
|
|
@ -461,7 +461,7 @@ proc parseTag(my: var XmlParser) =
|
||||||
proc parseEndTag(my: var XmlParser) =
|
proc parseEndTag(my: var XmlParser) =
|
||||||
inc(my.bufpos, 2)
|
inc(my.bufpos, 2)
|
||||||
parseName(my, my.a)
|
parseName(my, my.a)
|
||||||
parseWhitespace(my, skip=True)
|
parseWhitespace(my, skip=true)
|
||||||
if my.buf[my.bufpos] == '>':
|
if my.buf[my.bufpos] == '>':
|
||||||
inc(my.bufpos)
|
inc(my.bufpos)
|
||||||
else:
|
else:
|
||||||
|
|
@ -477,12 +477,12 @@ proc parseAttribute(my: var XmlParser) =
|
||||||
if my.a.len == 0:
|
if my.a.len == 0:
|
||||||
markError(my, errGtExpected)
|
markError(my, errGtExpected)
|
||||||
return
|
return
|
||||||
parseWhitespace(my, skip=True)
|
parseWhitespace(my, skip=true)
|
||||||
if my.buf[my.bufpos] != '=':
|
if my.buf[my.bufpos] != '=':
|
||||||
markError(my, errEqExpected)
|
markError(my, errEqExpected)
|
||||||
return
|
return
|
||||||
inc(my.bufpos)
|
inc(my.bufpos)
|
||||||
parseWhitespace(my, skip=True)
|
parseWhitespace(my, skip=true)
|
||||||
|
|
||||||
var pos = my.bufpos
|
var pos = my.bufpos
|
||||||
var buf = my.buf
|
var buf = my.buf
|
||||||
|
|
@ -507,11 +507,11 @@ proc parseAttribute(my: var XmlParser) =
|
||||||
pendingSpace = true
|
pendingSpace = true
|
||||||
inc(pos)
|
inc(pos)
|
||||||
of '\c':
|
of '\c':
|
||||||
pos = lexbase.HandleCR(my, pos)
|
pos = lexbase.handleCR(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
pendingSpace = true
|
pendingSpace = true
|
||||||
of '\L':
|
of '\L':
|
||||||
pos = lexbase.HandleLF(my, pos)
|
pos = lexbase.handleLF(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
pendingSpace = true
|
pendingSpace = true
|
||||||
else:
|
else:
|
||||||
|
|
@ -527,7 +527,7 @@ proc parseAttribute(my: var XmlParser) =
|
||||||
else:
|
else:
|
||||||
markError(my, errQuoteExpected)
|
markError(my, errQuoteExpected)
|
||||||
my.bufpos = pos
|
my.bufpos = pos
|
||||||
parseWhitespace(my, skip=True)
|
parseWhitespace(my, skip=true)
|
||||||
|
|
||||||
proc parseCharData(my: var XmlParser) =
|
proc parseCharData(my: var XmlParser) =
|
||||||
var pos = my.bufpos
|
var pos = my.bufpos
|
||||||
|
|
@ -537,11 +537,11 @@ proc parseCharData(my: var XmlParser) =
|
||||||
of '\0', '<', '&': break
|
of '\0', '<', '&': break
|
||||||
of '\c':
|
of '\c':
|
||||||
# the specification says that CR-LF, CR are to be transformed to LF
|
# the specification says that CR-LF, CR are to be transformed to LF
|
||||||
pos = lexbase.HandleCR(my, pos)
|
pos = lexbase.handleCR(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
add(my.a, '\L')
|
add(my.a, '\L')
|
||||||
of '\L':
|
of '\L':
|
||||||
pos = lexbase.HandleLF(my, pos)
|
pos = lexbase.handleLF(my, pos)
|
||||||
buf = my.buf
|
buf = my.buf
|
||||||
add(my.a, '\L')
|
add(my.a, '\L')
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ proc `&`*(a: string, b: Rope): Rope {.rtl, extern: "nroConcStrRope".} =
|
||||||
## the concatenation operator for ropes.
|
## the concatenation operator for ropes.
|
||||||
result = rope(a) & b
|
result = rope(a) & b
|
||||||
|
|
||||||
proc `&`*(a: openarray[Rope]): Rope {.rtl, extern: "nroConcOpenArray".} =
|
proc `&`*(a: openArray[Rope]): Rope {.rtl, extern: "nroConcOpenArray".} =
|
||||||
## the concatenation operator for an openarray of ropes.
|
## the concatenation operator for an openarray of ropes.
|
||||||
for i in countup(0, high(a)): result = result & a[i]
|
for i in countup(0, high(a)): result = result & a[i]
|
||||||
|
|
||||||
|
|
@ -233,7 +233,7 @@ iterator items*(r: Rope): char =
|
||||||
for s in leaves(r):
|
for s in leaves(r):
|
||||||
for c in items(s): yield c
|
for c in items(s): yield c
|
||||||
|
|
||||||
proc write*(f: TFile, r: Rope) {.rtl, extern: "nro$1".} =
|
proc write*(f: File, r: Rope) {.rtl, extern: "nro$1".} =
|
||||||
## writes a rope to a file.
|
## writes a rope to a file.
|
||||||
for s in leaves(r): write(f, s)
|
for s in leaves(r): write(f, s)
|
||||||
|
|
||||||
|
|
@ -291,7 +291,7 @@ when false:
|
||||||
if i - 1 >= start:
|
if i - 1 >= start:
|
||||||
add(result, substr(frmt, start, i-1))
|
add(result, substr(frmt, start, i-1))
|
||||||
|
|
||||||
proc `%`*(frmt: string, args: openarray[Rope]): Rope {.
|
proc `%`*(frmt: string, args: openArray[Rope]): Rope {.
|
||||||
rtl, extern: "nroFormat".} =
|
rtl, extern: "nroFormat".} =
|
||||||
## `%` substitution operator for ropes. Does not support the ``$identifier``
|
## `%` substitution operator for ropes. Does not support the ``$identifier``
|
||||||
## nor ``${identifier}`` notations.
|
## nor ``${identifier}`` notations.
|
||||||
|
|
@ -324,9 +324,9 @@ proc `%`*(frmt: string, args: openarray[Rope]): Rope {.
|
||||||
j = j * 10 + ord(frmt[i]) - ord('0')
|
j = j * 10 + ord(frmt[i]) - ord('0')
|
||||||
inc(i)
|
inc(i)
|
||||||
if frmt[i] == '}': inc(i)
|
if frmt[i] == '}': inc(i)
|
||||||
else: raise newException(EInvalidValue, "invalid format string")
|
else: raise newException(ValueError, "invalid format string")
|
||||||
add(result, args[j-1])
|
add(result, args[j-1])
|
||||||
else: raise newException(EInvalidValue, "invalid format string")
|
else: raise newException(ValueError, "invalid format string")
|
||||||
var start = i
|
var start = i
|
||||||
while i < length:
|
while i < length:
|
||||||
if frmt[i] != '$': inc(i)
|
if frmt[i] != '$': inc(i)
|
||||||
|
|
@ -334,15 +334,15 @@ proc `%`*(frmt: string, args: openarray[Rope]): Rope {.
|
||||||
if i - 1 >= start:
|
if i - 1 >= start:
|
||||||
add(result, substr(frmt, start, i - 1))
|
add(result, substr(frmt, start, i - 1))
|
||||||
|
|
||||||
proc addf*(c: var Rope, frmt: string, args: openarray[Rope]) {.
|
proc addf*(c: var Rope, frmt: string, args: openArray[Rope]) {.
|
||||||
rtl, extern: "nro$1".} =
|
rtl, extern: "nro$1".} =
|
||||||
## shortcut for ``add(c, frmt % args)``.
|
## shortcut for ``add(c, frmt % args)``.
|
||||||
add(c, frmt % args)
|
add(c, frmt % args)
|
||||||
|
|
||||||
proc equalsFile*(r: Rope, f: TFile): bool {.rtl, extern: "nro$1File".} =
|
proc equalsFile*(r: Rope, f: File): bool {.rtl, extern: "nro$1File".} =
|
||||||
## returns true if the contents of the file `f` equal `r`.
|
## returns true if the contents of the file `f` equal `r`.
|
||||||
var bufSize = 1024 # reasonable start value
|
var bufSize = 1024 # reasonable start value
|
||||||
var buf = alloc(BufSize)
|
var buf = alloc(bufSize)
|
||||||
for s in leaves(r):
|
for s in leaves(r):
|
||||||
if s.len > bufSize:
|
if s.len > bufSize:
|
||||||
bufSize = max(bufSize * 2, s.len)
|
bufSize = max(bufSize * 2, s.len)
|
||||||
|
|
@ -357,7 +357,7 @@ proc equalsFile*(r: Rope, f: TFile): bool {.rtl, extern: "nro$1File".} =
|
||||||
proc equalsFile*(r: Rope, f: string): bool {.rtl, extern: "nro$1Str".} =
|
proc equalsFile*(r: Rope, f: string): bool {.rtl, extern: "nro$1Str".} =
|
||||||
## returns true if the contents of the file `f` equal `r`. If `f` does not
|
## returns true if the contents of the file `f` equal `r`. If `f` does not
|
||||||
## exist, false is returned.
|
## exist, false is returned.
|
||||||
var bin: TFile
|
var bin: File
|
||||||
result = open(bin, f)
|
result = open(bin, f)
|
||||||
if result:
|
if result:
|
||||||
result = equalsFile(r, bin)
|
result = equalsFile(r, bin)
|
||||||
|
|
|
||||||
|
|
@ -2694,7 +2694,7 @@ elif defined(JS):
|
||||||
proc GC_disable() = discard
|
proc GC_disable() = discard
|
||||||
proc GC_enable() = discard
|
proc GC_enable() = discard
|
||||||
proc GC_fullCollect() = discard
|
proc GC_fullCollect() = discard
|
||||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
proc GC_setStrategy(strategy: GC_Strategy) = discard
|
||||||
proc GC_enableMarkAndSweep() = discard
|
proc GC_enableMarkAndSweep() = discard
|
||||||
proc GC_disableMarkAndSweep() = discard
|
proc GC_disableMarkAndSweep() = discard
|
||||||
proc GC_getStatistics(): string = return ""
|
proc GC_getStatistics(): string = return ""
|
||||||
|
|
@ -2706,7 +2706,7 @@ elif defined(JS):
|
||||||
proc dealloc(p: pointer) = discard
|
proc dealloc(p: pointer) = discard
|
||||||
proc alloc(size: int): pointer = discard
|
proc alloc(size: int): pointer = discard
|
||||||
proc alloc0(size: int): pointer = discard
|
proc alloc0(size: int): pointer = discard
|
||||||
proc realloc(p: Pointer, newsize: int): pointer = discard
|
proc realloc(p: pointer, newsize: int): pointer = discard
|
||||||
|
|
||||||
proc allocShared(size: int): pointer = discard
|
proc allocShared(size: int): pointer = discard
|
||||||
proc allocShared0(size: int): pointer = discard
|
proc allocShared0(size: int): pointer = discard
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ when someGcc and hasThreadSupport:
|
||||||
## with acquire loads
|
## with acquire loads
|
||||||
## and release stores in all threads.
|
## and release stores in all threads.
|
||||||
|
|
||||||
TAtomType* = TNumber|pointer|ptr|char
|
TAtomType* = SomeNumber|pointer|ptr|char
|
||||||
## Type Class representing valid types for use with atomic procs
|
## Type Class representing valid types for use with atomic procs
|
||||||
|
|
||||||
proc atomicLoadN*[T: TAtomType](p: ptr T, mem: AtomMemModel): T {.
|
proc atomicLoadN*[T: TAtomType](p: ptr T, mem: AtomMemModel): T {.
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,8 @@ proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
||||||
proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
|
proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
|
||||||
mode: TLoadStoreMode) {.gcsafe.} =
|
mode: TLoadStoreMode) {.gcsafe.} =
|
||||||
var
|
var
|
||||||
d = cast[TAddress](dest)
|
d = cast[ByteAddress](dest)
|
||||||
s = cast[TAddress](src)
|
s = cast[ByteAddress](src)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSlot: storeAux(cast[pointer](d +% n.offset),
|
of nkSlot: storeAux(cast[pointer](d +% n.offset),
|
||||||
cast[pointer](s +% n.offset), n.typ, t, mode)
|
cast[pointer](s +% n.offset), n.typ, t, mode)
|
||||||
|
|
@ -70,8 +70,8 @@ proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
|
||||||
proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
||||||
mode: TLoadStoreMode) =
|
mode: TLoadStoreMode) =
|
||||||
var
|
var
|
||||||
d = cast[TAddress](dest)
|
d = cast[ByteAddress](dest)
|
||||||
s = cast[TAddress](src)
|
s = cast[ByteAddress](src)
|
||||||
sysAssert(mt != nil, "mt == nil")
|
sysAssert(mt != nil, "mt == nil")
|
||||||
case mt.kind
|
case mt.kind
|
||||||
of tyString:
|
of tyString:
|
||||||
|
|
@ -108,11 +108,11 @@ proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
||||||
x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)
|
x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)
|
||||||
else:
|
else:
|
||||||
unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
||||||
var dst = cast[TAddress](cast[PPointer](dest)[])
|
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
||||||
for i in 0..seq.len-1:
|
for i in 0..seq.len-1:
|
||||||
storeAux(
|
storeAux(
|
||||||
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
|
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
|
||||||
cast[pointer](cast[TAddress](s2) +% i *% mt.base.size +%
|
cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%
|
||||||
GenericSeqSize),
|
GenericSeqSize),
|
||||||
mt.base, t, mode)
|
mt.base, t, mode)
|
||||||
var dstseq = cast[PGenericSeq](dst)
|
var dstseq = cast[PGenericSeq](dst)
|
||||||
|
|
@ -192,7 +192,7 @@ template lockChannel(q: expr, action: stmt) {.immediate.} =
|
||||||
|
|
||||||
template sendImpl(q: expr) {.immediate.} =
|
template sendImpl(q: expr) {.immediate.} =
|
||||||
if q.mask == ChannelDeadMask:
|
if q.mask == ChannelDeadMask:
|
||||||
sysFatal(EDeadThread, "cannot send message; thread died")
|
sysFatal(DeadThreadError, "cannot send message; thread died")
|
||||||
acquireSys(q.lock)
|
acquireSys(q.lock)
|
||||||
var m: TMsg
|
var m: TMsg
|
||||||
shallowCopy(m, msg)
|
shallowCopy(m, msg)
|
||||||
|
|
@ -215,7 +215,7 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
|
||||||
q.ready = false
|
q.ready = false
|
||||||
if typ != q.elemType:
|
if typ != q.elemType:
|
||||||
releaseSys(q.lock)
|
releaseSys(q.lock)
|
||||||
sysFatal(EInvalidValue, "cannot receive message of wrong type")
|
sysFatal(ValueError, "cannot receive message of wrong type")
|
||||||
rawRecv(q, res, typ)
|
rawRecv(q, res, typ)
|
||||||
|
|
||||||
proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
|
proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
|
||||||
|
|
|
||||||
|
|
@ -80,11 +80,11 @@ template gcAssert(cond: bool, msg: string) =
|
||||||
|
|
||||||
proc cellToUsr(cell: PCell): pointer {.inline.} =
|
proc cellToUsr(cell: PCell): pointer {.inline.} =
|
||||||
# convert object (=pointer to refcount) to pointer to userdata
|
# convert object (=pointer to refcount) to pointer to userdata
|
||||||
result = cast[pointer](cast[TAddress](cell)+%TAddress(sizeof(TCell)))
|
result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(TCell)))
|
||||||
|
|
||||||
proc usrToCell(usr: pointer): PCell {.inline.} =
|
proc usrToCell(usr: pointer): PCell {.inline.} =
|
||||||
# convert pointer to userdata to object (=pointer to refcount)
|
# convert pointer to userdata to object (=pointer to refcount)
|
||||||
result = cast[PCell](cast[TAddress](usr)-%TAddress(sizeof(TCell)))
|
result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
|
||||||
|
|
||||||
proc canbeCycleRoot(c: PCell): bool {.inline.} =
|
proc canbeCycleRoot(c: PCell): bool {.inline.} =
|
||||||
result = ntfAcyclic notin c.typ.flags
|
result = ntfAcyclic notin c.typ.flags
|
||||||
|
|
@ -169,7 +169,7 @@ proc initGC() =
|
||||||
init(gch.marked)
|
init(gch.marked)
|
||||||
|
|
||||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.gcsafe.} =
|
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.gcsafe.} =
|
||||||
var d = cast[TAddress](dest)
|
var d = cast[ByteAddress](dest)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
|
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
|
||||||
of nkList:
|
of nkList:
|
||||||
|
|
@ -181,7 +181,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.gcsafe.} =
|
||||||
of nkNone: sysAssert(false, "forAllSlotsAux")
|
of nkNone: sysAssert(false, "forAllSlotsAux")
|
||||||
|
|
||||||
proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
|
proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
|
||||||
var d = cast[TAddress](dest)
|
var d = cast[ByteAddress](dest)
|
||||||
if dest == nil: return # nothing to do
|
if dest == nil: return # nothing to do
|
||||||
if ntfNoRefs notin mt.flags:
|
if ntfNoRefs notin mt.flags:
|
||||||
case mt.kind
|
case mt.kind
|
||||||
|
|
@ -206,7 +206,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||||
of tyRef: # common case
|
of tyRef: # common case
|
||||||
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
var d = cast[TAddress](cellToUsr(cell))
|
var d = cast[ByteAddress](cellToUsr(cell))
|
||||||
var s = cast[PGenericSeq](d)
|
var s = cast[PGenericSeq](d)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
for i in 0..s.len-1:
|
for i in 0..s.len-1:
|
||||||
|
|
@ -220,7 +220,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
|
||||||
gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
|
gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
|
||||||
collectCT(gch)
|
collectCT(gch)
|
||||||
var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
|
var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
|
||||||
gcAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
|
gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
|
||||||
# now it is buffered in the ZCT
|
# now it is buffered in the ZCT
|
||||||
res.typ = typ
|
res.typ = typ
|
||||||
when leakDetector and not hasThreadSupport:
|
when leakDetector and not hasThreadSupport:
|
||||||
|
|
@ -280,9 +280,9 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
|
||||||
|
|
||||||
var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
|
var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
|
||||||
copyMem(res, ol, oldsize + sizeof(TCell))
|
copyMem(res, ol, oldsize + sizeof(TCell))
|
||||||
zeroMem(cast[pointer](cast[TAddress](res)+% oldsize +% sizeof(TCell)),
|
zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
|
||||||
newsize-oldsize)
|
newsize-oldsize)
|
||||||
sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
|
sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
|
||||||
when withBitvectors: excl(gch.allocated, ol)
|
when withBitvectors: excl(gch.allocated, ol)
|
||||||
when reallyDealloc: rawDealloc(gch.region, ol)
|
when reallyDealloc: rawDealloc(gch.region, ol)
|
||||||
else:
|
else:
|
||||||
|
|
@ -379,7 +379,7 @@ proc markGlobals(gch: var TGcHeap) =
|
||||||
proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
|
proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
|
||||||
# the addresses are not as cells on the stack, so turn them to cells:
|
# the addresses are not as cells on the stack, so turn them to cells:
|
||||||
var cell = usrToCell(p)
|
var cell = usrToCell(p)
|
||||||
var c = cast[TAddress](cell)
|
var c = cast[ByteAddress](cell)
|
||||||
if c >% PageSize:
|
if c >% PageSize:
|
||||||
# fast check: does it look like a cell?
|
# fast check: does it look like a cell?
|
||||||
var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
|
var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
|
||||||
|
|
@ -404,8 +404,8 @@ when not defined(useNimRtl):
|
||||||
# the first init must be the one that defines the stack bottom:
|
# the first init must be the one that defines the stack bottom:
|
||||||
if gch.stackBottom == nil: gch.stackBottom = theStackBottom
|
if gch.stackBottom == nil: gch.stackBottom = theStackBottom
|
||||||
else:
|
else:
|
||||||
var a = cast[TAddress](theStackBottom) # and not PageMask - PageSize*2
|
var a = cast[ByteAddress](theStackBottom) # and not PageMask - PageSize*2
|
||||||
var b = cast[TAddress](gch.stackBottom)
|
var b = cast[ByteAddress](gch.stackBottom)
|
||||||
#c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom)
|
#c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom)
|
||||||
when stackIncreases:
|
when stackIncreases:
|
||||||
gch.stackBottom = cast[pointer](min(a, b))
|
gch.stackBottom = cast[pointer](min(a, b))
|
||||||
|
|
@ -421,9 +421,9 @@ when defined(sparc): # For SPARC architecture.
|
||||||
proc isOnStack(p: pointer): bool =
|
proc isOnStack(p: pointer): bool =
|
||||||
var stackTop {.volatile.}: pointer
|
var stackTop {.volatile.}: pointer
|
||||||
stackTop = addr(stackTop)
|
stackTop = addr(stackTop)
|
||||||
var b = cast[TAddress](gch.stackBottom)
|
var b = cast[ByteAddress](gch.stackBottom)
|
||||||
var a = cast[TAddress](stackTop)
|
var a = cast[ByteAddress](stackTop)
|
||||||
var x = cast[TAddress](p)
|
var x = cast[ByteAddress](p)
|
||||||
result = a <=% x and x <=% b
|
result = a <=% x and x <=% b
|
||||||
|
|
||||||
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
|
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
|
||||||
|
|
@ -440,7 +440,7 @@ when defined(sparc): # For SPARC architecture.
|
||||||
# Addresses decrease as the stack grows.
|
# Addresses decrease as the stack grows.
|
||||||
while sp <= max:
|
while sp <= max:
|
||||||
gcMark(gch, sp[])
|
gcMark(gch, sp[])
|
||||||
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
|
sp = cast[ppointer](cast[ByteAddress](sp) +% sizeof(pointer))
|
||||||
|
|
||||||
elif defined(ELATE):
|
elif defined(ELATE):
|
||||||
{.error: "stack marking code is to be written for this architecture".}
|
{.error: "stack marking code is to be written for this architecture".}
|
||||||
|
|
@ -452,9 +452,9 @@ elif stackIncreases:
|
||||||
proc isOnStack(p: pointer): bool =
|
proc isOnStack(p: pointer): bool =
|
||||||
var stackTop {.volatile.}: pointer
|
var stackTop {.volatile.}: pointer
|
||||||
stackTop = addr(stackTop)
|
stackTop = addr(stackTop)
|
||||||
var a = cast[TAddress](gch.stackBottom)
|
var a = cast[ByteAddress](gch.stackBottom)
|
||||||
var b = cast[TAddress](stackTop)
|
var b = cast[ByteAddress](stackTop)
|
||||||
var x = cast[TAddress](p)
|
var x = cast[ByteAddress](p)
|
||||||
result = a <=% x and x <=% b
|
result = a <=% x and x <=% b
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -465,8 +465,8 @@ elif stackIncreases:
|
||||||
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
|
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
|
||||||
var registers: C_JmpBuf
|
var registers: C_JmpBuf
|
||||||
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
|
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
|
||||||
var max = cast[TAddress](gch.stackBottom)
|
var max = cast[ByteAddress](gch.stackBottom)
|
||||||
var sp = cast[TAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
|
var sp = cast[ByteAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
|
||||||
# sp will traverse the JMP_BUF as well (jmp_buf size is added,
|
# sp will traverse the JMP_BUF as well (jmp_buf size is added,
|
||||||
# otherwise sp would be below the registers structure).
|
# otherwise sp would be below the registers structure).
|
||||||
while sp >=% max:
|
while sp >=% max:
|
||||||
|
|
@ -480,9 +480,9 @@ else:
|
||||||
proc isOnStack(p: pointer): bool =
|
proc isOnStack(p: pointer): bool =
|
||||||
var stackTop {.volatile.}: pointer
|
var stackTop {.volatile.}: pointer
|
||||||
stackTop = addr(stackTop)
|
stackTop = addr(stackTop)
|
||||||
var b = cast[TAddress](gch.stackBottom)
|
var b = cast[ByteAddress](gch.stackBottom)
|
||||||
var a = cast[TAddress](stackTop)
|
var a = cast[ByteAddress](stackTop)
|
||||||
var x = cast[TAddress](p)
|
var x = cast[ByteAddress](p)
|
||||||
result = a <=% x and x <=% b
|
result = a <=% x and x <=% b
|
||||||
|
|
||||||
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
|
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
|
||||||
|
|
@ -492,8 +492,8 @@ else:
|
||||||
type PStackSlice = ptr array [0..7, pointer]
|
type PStackSlice = ptr array [0..7, pointer]
|
||||||
var registers {.noinit.}: C_JmpBuf
|
var registers {.noinit.}: C_JmpBuf
|
||||||
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
|
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
|
||||||
var max = cast[TAddress](gch.stackBottom)
|
var max = cast[ByteAddress](gch.stackBottom)
|
||||||
var sp = cast[TAddress](addr(registers))
|
var sp = cast[ByteAddress](addr(registers))
|
||||||
# loop unrolled:
|
# loop unrolled:
|
||||||
while sp <% max - 8*sizeof(pointer):
|
while sp <% max - 8*sizeof(pointer):
|
||||||
gcMark(gch, cast[PStackSlice](sp)[0])
|
gcMark(gch, cast[PStackSlice](sp)[0])
|
||||||
|
|
@ -546,7 +546,7 @@ when not defined(useNimRtl):
|
||||||
else:
|
else:
|
||||||
dec(gch.recGcLock)
|
dec(gch.recGcLock)
|
||||||
|
|
||||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
proc GC_setStrategy(strategy: GC_Strategy) = discard
|
||||||
|
|
||||||
proc GC_enableMarkAndSweep() =
|
proc GC_enableMarkAndSweep() =
|
||||||
gch.cycleThreshold = InitialThreshold
|
gch.cycleThreshold = InitialThreshold
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ type
|
||||||
PSafePoint = ptr TSafePoint
|
PSafePoint = ptr TSafePoint
|
||||||
TSafePoint {.compilerproc, final.} = object
|
TSafePoint {.compilerproc, final.} = object
|
||||||
prev: PSafePoint # points to next safe point
|
prev: PSafePoint # points to next safe point
|
||||||
exc: ref E_Base
|
exc: ref Exception
|
||||||
|
|
||||||
PCallFrame = ptr TCallFrame
|
PCallFrame = ptr TCallFrame
|
||||||
TCallFrame {.importc, nodecl, final.} = object
|
TCallFrame {.importc, nodecl, final.} = object
|
||||||
|
|
@ -97,7 +97,7 @@ proc rawWriteStackTrace(): string =
|
||||||
else:
|
else:
|
||||||
result = "No stack traceback available\n"
|
result = "No stack traceback available\n"
|
||||||
|
|
||||||
proc raiseException(e: ref E_Base, ename: cstring) {.
|
proc raiseException(e: ref Exception, ename: cstring) {.
|
||||||
compilerproc, asmNoStackFrame.} =
|
compilerproc, asmNoStackFrame.} =
|
||||||
e.name = ename
|
e.name = ename
|
||||||
if excHandler != nil:
|
if excHandler != nil:
|
||||||
|
|
@ -120,24 +120,24 @@ proc raiseException(e: ref E_Base, ename: cstring) {.
|
||||||
|
|
||||||
proc reraiseException() {.compilerproc, asmNoStackFrame.} =
|
proc reraiseException() {.compilerproc, asmNoStackFrame.} =
|
||||||
if excHandler == nil:
|
if excHandler == nil:
|
||||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
raise newException(ReraiseError, "no exception to reraise")
|
||||||
else:
|
else:
|
||||||
asm """throw excHandler.exc;"""
|
asm """throw excHandler.exc;"""
|
||||||
|
|
||||||
proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} =
|
proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} =
|
||||||
raise newException(EOverflow, "over- or underflow")
|
raise newException(OverflowError, "over- or underflow")
|
||||||
|
|
||||||
proc raiseDivByZero {.exportc: "raiseDivByZero", noreturn.} =
|
proc raiseDivByZero {.exportc: "raiseDivByZero", noreturn.} =
|
||||||
raise newException(EDivByZero, "divison by zero")
|
raise newException(DivByZeroError, "divison by zero")
|
||||||
|
|
||||||
proc raiseRangeError() {.compilerproc, noreturn.} =
|
proc raiseRangeError() {.compilerproc, noreturn.} =
|
||||||
raise newException(EOutOfRange, "value out of range")
|
raise newException(RangeError, "value out of range")
|
||||||
|
|
||||||
proc raiseIndexError() {.compilerproc, noreturn.} =
|
proc raiseIndexError() {.compilerproc, noreturn.} =
|
||||||
raise newException(EInvalidIndex, "index out of bounds")
|
raise newException(IndexError, "index out of bounds")
|
||||||
|
|
||||||
proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
|
proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
|
||||||
raise newException(EInvalidField, f & " is not accessible")
|
raise newException(FieldError, f & " is not accessible")
|
||||||
|
|
||||||
proc SetConstr() {.varargs, asmNoStackFrame, compilerproc.} =
|
proc SetConstr() {.varargs, asmNoStackFrame, compilerproc.} =
|
||||||
asm """
|
asm """
|
||||||
|
|
@ -260,7 +260,7 @@ proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerProc.} =
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
TDocument {.importc.} = object of TObject
|
TDocument {.importc.} = object of RootObj
|
||||||
write: proc (text: cstring) {.nimcall.}
|
write: proc (text: cstring) {.nimcall.}
|
||||||
writeln: proc (text: cstring) {.nimcall.}
|
writeln: proc (text: cstring) {.nimcall.}
|
||||||
createAttribute: proc (identifier: cstring): ref TNode {.nimcall.}
|
createAttribute: proc (identifier: cstring): ref TNode {.nimcall.}
|
||||||
|
|
@ -283,7 +283,7 @@ type
|
||||||
DocumentTypeNode,
|
DocumentTypeNode,
|
||||||
DocumentFragmentNode,
|
DocumentFragmentNode,
|
||||||
NotationNode
|
NotationNode
|
||||||
TNode* {.importc.} = object of TObject
|
TNode* {.importc.} = object of RootObj
|
||||||
attributes*: seq[ref TNode]
|
attributes*: seq[ref TNode]
|
||||||
childNodes*: seq[ref TNode]
|
childNodes*: seq[ref TNode]
|
||||||
data*: cstring
|
data*: cstring
|
||||||
|
|
@ -515,7 +515,7 @@ proc isFatPointer(ti: PNimType): bool =
|
||||||
|
|
||||||
proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
|
proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
|
||||||
|
|
||||||
proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} =
|
proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkNone: sysAssert(false, "nimCopyAux")
|
of nkNone: sysAssert(false, "nimCopyAux")
|
||||||
of nkSlot:
|
of nkSlot:
|
||||||
|
|
@ -566,7 +566,7 @@ proc nimCopy(x: pointer, ti: PNimType): pointer =
|
||||||
else:
|
else:
|
||||||
result = x
|
result = x
|
||||||
|
|
||||||
proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} =
|
proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} =
|
||||||
case ti.kind
|
case ti.kind
|
||||||
of tyPtr, tyRef, tyVar, tyNil:
|
of tyPtr, tyRef, tyVar, tyNil:
|
||||||
if not isFatPointer(ti):
|
if not isFatPointer(ti):
|
||||||
|
|
@ -621,7 +621,7 @@ proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||||
if x == subclass: return # optimized fast path
|
if x == subclass: return # optimized fast path
|
||||||
while x != subclass:
|
while x != subclass:
|
||||||
if x == nil:
|
if x == nil:
|
||||||
raise newException(EInvalidObjectConversion, "invalid object conversion")
|
raise newException(ObjectConversionError, "invalid object conversion")
|
||||||
x = x.base
|
x = x.base
|
||||||
|
|
||||||
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
||||||
|
|
|
||||||
|
|
@ -305,22 +305,26 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
|
||||||
## returns true if `t` is running.
|
## returns true if `t` is running.
|
||||||
result = t.dataFn != nil
|
result = t.dataFn != nil
|
||||||
|
|
||||||
|
when hostOS == "windows":
|
||||||
proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
|
proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
|
||||||
## waits for the thread `t` to finish.
|
## waits for the thread `t` to finish.
|
||||||
when hostOS == "windows":
|
|
||||||
discard waitForSingleObject(t.sys, -1'i32)
|
discard waitForSingleObject(t.sys, -1'i32)
|
||||||
else:
|
|
||||||
discard pthread_join(t.sys, nil)
|
|
||||||
|
|
||||||
proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
|
proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
|
||||||
## waits for every thread in `t` to finish.
|
## waits for every thread in `t` to finish.
|
||||||
when hostOS == "windows":
|
|
||||||
var a: array[0..255, TSysThread]
|
var a: array[0..255, TSysThread]
|
||||||
sysAssert a.len >= t.len, "a.len >= t.len"
|
sysAssert a.len >= t.len, "a.len >= t.len"
|
||||||
for i in 0..t.high: a[i] = t[i].sys
|
for i in 0..t.high: a[i] = t[i].sys
|
||||||
discard waitForMultipleObjects(t.len.int32,
|
discard waitForMultipleObjects(t.len.int32,
|
||||||
cast[ptr TSysThread](addr(a)), 1, -1)
|
cast[ptr TSysThread](addr(a)), 1, -1)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
|
||||||
|
## waits for the thread `t` to finish.
|
||||||
|
discard pthread_join(t.sys, nil)
|
||||||
|
|
||||||
|
proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
|
||||||
|
## waits for every thread in `t` to finish.
|
||||||
for i in 0..t.high: joinThread(t[i])
|
for i in 0..t.high: joinThread(t[i])
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
|
|
@ -335,6 +339,7 @@ when false:
|
||||||
when declared(registerThread): unregisterThread(addr(t))
|
when declared(registerThread): unregisterThread(addr(t))
|
||||||
t.dataFn = nil
|
t.dataFn = nil
|
||||||
|
|
||||||
|
when hostOS == "windows":
|
||||||
proc createThread*[TArg](t: var TThread[TArg],
|
proc createThread*[TArg](t: var TThread[TArg],
|
||||||
tp: proc (arg: TArg) {.thread.},
|
tp: proc (arg: TArg) {.thread.},
|
||||||
param: TArg) =
|
param: TArg) =
|
||||||
|
|
@ -344,18 +349,27 @@ proc createThread*[TArg](t: var TThread[TArg],
|
||||||
when TArg isnot void: t.data = param
|
when TArg isnot void: t.data = param
|
||||||
t.dataFn = tp
|
t.dataFn = tp
|
||||||
when hasSharedHeap: t.stackSize = ThreadStackSize
|
when hasSharedHeap: t.stackSize = ThreadStackSize
|
||||||
when hostOS == "windows":
|
|
||||||
var dummyThreadId: int32
|
var dummyThreadId: int32
|
||||||
t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
|
t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
|
||||||
addr(t), 0'i32, dummyThreadId)
|
addr(t), 0'i32, dummyThreadId)
|
||||||
if t.sys <= 0:
|
if t.sys <= 0:
|
||||||
raise newException(EResourceExhausted, "cannot create thread")
|
raise newException(ResourceExhaustedError, "cannot create thread")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
proc createThread*[TArg](t: var TThread[TArg],
|
||||||
|
tp: proc (arg: TArg) {.thread.},
|
||||||
|
param: TArg) =
|
||||||
|
## creates a new thread `t` and starts its execution. Entry point is the
|
||||||
|
## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
|
||||||
|
## don't need to pass any data to the thread.
|
||||||
|
when TArg isnot void: t.data = param
|
||||||
|
t.dataFn = tp
|
||||||
|
when hasSharedHeap: t.stackSize = ThreadStackSize
|
||||||
var a {.noinit.}: Tpthread_attr
|
var a {.noinit.}: Tpthread_attr
|
||||||
pthread_attr_init(a)
|
pthread_attr_init(a)
|
||||||
pthread_attr_setstacksize(a, ThreadStackSize)
|
pthread_attr_setstacksize(a, ThreadStackSize)
|
||||||
if pthread_create(t.sys, a, threadProcWrapper[TArg], addr(t)) != 0:
|
if pthread_create(t.sys, a, threadProcWrapper[TArg], addr(t)) != 0:
|
||||||
raise newException(EResourceExhausted, "cannot create thread")
|
raise newException(ResourceExhaustedError, "cannot create thread")
|
||||||
|
|
||||||
proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} =
|
proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} =
|
||||||
## returns the thread ID of `t`.
|
## returns the thread ID of `t`.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ discard """
|
||||||
# Test the case statement
|
# Test the case statement
|
||||||
|
|
||||||
type
|
type
|
||||||
tenum = enum eA, eB, eC
|
Tenum = enum eA, eB, eC
|
||||||
|
|
||||||
var
|
var
|
||||||
x: string = "yyy"
|
x: string = "yyy"
|
||||||
|
|
|
||||||
|
|
@ -20,46 +20,46 @@ proc threadFunc(interval: tuple[a, b: int]) {.thread.} =
|
||||||
when nodeadlocks:
|
when nodeadlocks:
|
||||||
case i mod 6
|
case i mod 6
|
||||||
of 0:
|
of 0:
|
||||||
Acquire(L) # lock stdout
|
acquire(L) # lock stdout
|
||||||
Acquire(M)
|
acquire(M)
|
||||||
Acquire(N)
|
acquire(N)
|
||||||
of 1:
|
of 1:
|
||||||
Acquire(L)
|
acquire(L)
|
||||||
Acquire(N) # lock stdout
|
acquire(N) # lock stdout
|
||||||
Acquire(M)
|
acquire(M)
|
||||||
of 2:
|
of 2:
|
||||||
Acquire(M)
|
acquire(M)
|
||||||
Acquire(L)
|
acquire(L)
|
||||||
Acquire(N)
|
acquire(N)
|
||||||
of 3:
|
of 3:
|
||||||
Acquire(M)
|
acquire(M)
|
||||||
Acquire(N)
|
acquire(N)
|
||||||
Acquire(L)
|
acquire(L)
|
||||||
of 4:
|
of 4:
|
||||||
Acquire(N)
|
acquire(N)
|
||||||
Acquire(M)
|
acquire(M)
|
||||||
Acquire(L)
|
acquire(L)
|
||||||
of 5:
|
of 5:
|
||||||
Acquire(N)
|
acquire(N)
|
||||||
Acquire(L)
|
acquire(L)
|
||||||
Acquire(M)
|
acquire(M)
|
||||||
else: assert false
|
else: assert false
|
||||||
else:
|
else:
|
||||||
Acquire(L) # lock stdout
|
acquire(L) # lock stdout
|
||||||
Acquire(M)
|
acquire(M)
|
||||||
|
|
||||||
echo i
|
echo i
|
||||||
os.sleep(10)
|
os.sleep(10)
|
||||||
when nodeadlocks:
|
when nodeadlocks:
|
||||||
echo "deadlocks prevented: ", deadlocksPrevented
|
echo "deadlocks prevented: ", deadlocksPrevented
|
||||||
when nodeadlocks:
|
when nodeadlocks:
|
||||||
Release(N)
|
release(N)
|
||||||
Release(M)
|
release(M)
|
||||||
Release(L)
|
release(L)
|
||||||
|
|
||||||
InitLock(L)
|
initLock(L)
|
||||||
InitLock(M)
|
initLock(M)
|
||||||
InitLock(N)
|
initLock(N)
|
||||||
|
|
||||||
proc main =
|
proc main =
|
||||||
for i in 0..high(thr):
|
for i in 0..high(thr):
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ type
|
||||||
s: string,
|
s: string,
|
||||||
x, y: int,
|
x, y: int,
|
||||||
z: float,
|
z: float,
|
||||||
chars: set[Char]]
|
chars: set[char]]
|
||||||
|
|
||||||
proc testSem =
|
proc testSem =
|
||||||
var
|
var
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tfloat1.nim"
|
file: "tfloat1.nim"
|
||||||
outputsub: "Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]"
|
outputsub: "Error: unhandled exception: FPU operation caused an overflow [FloatOverflowError]"
|
||||||
exitcode: "1"
|
exitcode: "1"
|
||||||
"""
|
"""
|
||||||
# Test new floating point exceptions
|
# Test new floating point exceptions
|
||||||
|
|
@ -10,6 +10,6 @@ discard """
|
||||||
var x = 0.8
|
var x = 0.8
|
||||||
var y = 0.0
|
var y = 0.0
|
||||||
|
|
||||||
echo x / y #OUT Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]
|
echo x / y #OUT Error: unhandled exception: FPU operation caused an overflow
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tfloat2.nim"
|
file: "tfloat2.nim"
|
||||||
outputsub: "Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]"
|
outputsub: "Error: unhandled exception: FPU operation caused a NaN result [FloatInvalidOpError]"
|
||||||
exitcode: "1"
|
exitcode: "1"
|
||||||
"""
|
"""
|
||||||
# Test new floating point exceptions
|
# Test new floating point exceptions
|
||||||
|
|
@ -10,6 +10,6 @@ discard """
|
||||||
var x = 0.0
|
var x = 0.0
|
||||||
var y = 0.0
|
var y = 0.0
|
||||||
|
|
||||||
echo x / y #OUT Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]
|
echo x / y #OUT Error: unhandled exception: FPU operation caused a NaN result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ void printFloats(void) {
|
||||||
}
|
}
|
||||||
""".}
|
""".}
|
||||||
|
|
||||||
proc c_printf(frmt: CString) {.importc: "printf", header: "<stdio.h>", varargs.}
|
proc c_printf(frmt: cstring) {.importc: "printf", header: "<stdio.h>", varargs.}
|
||||||
proc printFloats {.importc, nodecl.}
|
proc printFloats {.importc, nodecl.}
|
||||||
|
|
||||||
var x: float = 1.234567890123456789
|
var x: float = 1.234567890123456789
|
||||||
|
|
|
||||||
|
|
@ -29,5 +29,5 @@ for i in 0 .. <10:
|
||||||
f.func = proc =
|
f.func = proc =
|
||||||
echo f.id
|
echo f.id
|
||||||
|
|
||||||
gc_fullcollect()
|
GC_fullcollect()
|
||||||
echo alive_foos.len <= 3
|
echo alive_foos.len <= 3
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ proc newDict*[TKey, TValue](): PDict[TKey, TValue] =
|
||||||
proc add*[TKey, TValue](d: PDict[TKey, TValue], k: TKey, v: TValue) =
|
proc add*[TKey, TValue](d: PDict[TKey, TValue], k: TKey, v: TValue) =
|
||||||
d.data.add((k, v))
|
d.data.add((k, v))
|
||||||
|
|
||||||
iterator items*[Tkey, tValue](d: PDict[TKey, TValue]): tuple[k: TKey,
|
iterator items*[Tkey, TValue](d: PDict[TKey, TValue]): tuple[k: TKey,
|
||||||
v: TValue] =
|
v: TValue] =
|
||||||
for k, v in items(d.data): yield (k, v)
|
for k, v in items(d.data): yield (k, v)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import tables
|
import tables
|
||||||
|
|
||||||
type
|
type
|
||||||
TX = TTable[string, int]
|
TX = Table[string, int]
|
||||||
|
|
||||||
proc foo(models: seq[TX]): seq[int] =
|
proc foo(models: seq[TX]): seq[int] =
|
||||||
result = @[]
|
result = @[]
|
||||||
|
|
@ -9,7 +9,7 @@ proc foo(models: seq[TX]): seq[int] =
|
||||||
result.add model["foobar"]
|
result.add model["foobar"]
|
||||||
|
|
||||||
type
|
type
|
||||||
obj = object
|
Obj = object
|
||||||
field: TTable[string, string]
|
field: Table[string, string]
|
||||||
var t: Obj
|
var t: Obj
|
||||||
discard initTable[type(t.field), string]()
|
discard initTable[type(t.field), string]()
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,17 @@ type
|
||||||
value: D
|
value: D
|
||||||
node: PNode[T,D]
|
node: PNode[T,D]
|
||||||
when not (D is string):
|
when not (D is string):
|
||||||
val_set: Bool
|
val_set: bool
|
||||||
|
|
||||||
TItems[T,D] = seq[ref TItem[T,D]]
|
TItems[T,D] = seq[ref TItem[T,D]]
|
||||||
TNode {.acyclic, pure, final, shallow.} [T,D] = object
|
TNode {.acyclic, pure, final, shallow.} [T,D] = object
|
||||||
slots: TItems[T,D]
|
slots: TItems[T,D]
|
||||||
left: PNode[T,D]
|
left: PNode[T,D]
|
||||||
count: Int32
|
count: int32
|
||||||
|
|
||||||
|
|
||||||
RPath[T,D] = tuple[
|
RPath[T,D] = tuple[
|
||||||
Xi: Int,
|
Xi: int,
|
||||||
Nd: PNode[T,D] ]
|
Nd: PNode[T,D] ]
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -29,41 +29,41 @@ const
|
||||||
cLenMax = 128
|
cLenMax = 128
|
||||||
cCenter = cLenMax div 2
|
cCenter = cLenMax div 2
|
||||||
|
|
||||||
proc len[T,D] (n:PNode[T,D]): Int {.inline.} =
|
proc len[T,D] (n:PNode[T,D]): int {.inline.} =
|
||||||
return n.Count
|
return n.count
|
||||||
|
|
||||||
proc clean[T: TOrdinal|TNumber](o: var T) {.inline.} = discard
|
proc clean[T: SomeOrdinal|SomeNumber](o: var T) {.inline.} = discard
|
||||||
|
|
||||||
proc clean[T: string|seq](o: var T) {.inline.} =
|
proc clean[T: string|seq](o: var T) {.inline.} =
|
||||||
o = nil
|
o = nil
|
||||||
|
|
||||||
proc clean[T,D] (o: ref TItem[T,D]) {.inline.} =
|
proc clean[T,D] (o: ref TItem[T,D]) {.inline.} =
|
||||||
when (D is string) :
|
when (D is string) :
|
||||||
o.Value = nil
|
o.value = nil
|
||||||
else :
|
else :
|
||||||
o.val_set = false
|
o.val_set = false
|
||||||
|
|
||||||
proc isClean[T,D] (it: ref TItem[T,D]): Bool {.inline.} =
|
proc isClean[T,D] (it: ref TItem[T,D]): bool {.inline.} =
|
||||||
when (D is string) :
|
when (D is string) :
|
||||||
return it.Value == nil
|
return it.value == nil
|
||||||
else :
|
else :
|
||||||
return not it.val_set
|
return not it.val_set
|
||||||
|
|
||||||
proc isClean[T,D] (n: PNode[T,D], x: Int): Bool {.inline.} =
|
proc isClean[T,D](n: PNode[T,D], x: int): bool {.inline.} =
|
||||||
when (D is string):
|
when (D is string):
|
||||||
return n.slots[x].Value == nil
|
return n.slots[x].value == nil
|
||||||
else:
|
else:
|
||||||
return not n.slots[x].val_set
|
return not n.slots[x].val_set
|
||||||
|
|
||||||
proc setItem[T,D] (AKey: T, AValue: D, ANode: PNode[T,D]): ref TItem[T,D] {.inline.} =
|
proc setItem[T,D](Akey: T, Avalue: D, ANode: PNode[T,D]): ref TItem[T,D] {.inline.} =
|
||||||
new(Result)
|
new(result)
|
||||||
Result.Key = AKey
|
result.key = Akey
|
||||||
Result.Value = AValue
|
result.value = Avalue
|
||||||
Result.Node = ANode
|
result.node = ANode
|
||||||
when not (D is string) :
|
when not (D is string) :
|
||||||
Result.val_set = true
|
result.val_set = true
|
||||||
|
|
||||||
proc cmp[T:Int8|Int16|Int32|Int64|Int] (a,b: T): T {.inline.} =
|
proc cmp[T:int8|int16|int32|int64|int] (a,b: T): T {.inline.} =
|
||||||
return a-b
|
return a-b
|
||||||
|
|
||||||
template binSearchImpl *(docmp: expr) {.immediate.} =
|
template binSearchImpl *(docmp: expr) {.immediate.} =
|
||||||
|
|
@ -76,41 +76,41 @@ template binSearchImpl *(docmp: expr) {.immediate.} =
|
||||||
if SW < 0: result = I + 1
|
if SW < 0: result = I + 1
|
||||||
else:
|
else:
|
||||||
H = I - 1
|
H = I - 1
|
||||||
if SW == 0 : bFound = True
|
if SW == 0 : bFound = true
|
||||||
if bFound: inc(result)
|
if bFound: inc(result)
|
||||||
else: result = - result
|
else: result = - result
|
||||||
|
|
||||||
proc bSearch[T,D] (haystack: PNode[T,D], needle:T): Int {.inline.} =
|
proc bSearch[T,D] (haystack: PNode[T,D], needle:T): int {.inline.} =
|
||||||
binSearchImpl(haystack.slots[I].key.cmp(needle))
|
binSearchImpl(haystack.slots[I].key.cmp(needle))
|
||||||
|
|
||||||
proc DeleteItem[T,D] (n: PNode[T,D], x: Int): PNode[T,D] {.inline.} =
|
proc DeleteItem[T,D] (n: PNode[T,D], x: int): PNode[T,D] {.inline.} =
|
||||||
var w = n.slots[x]
|
var w = n.slots[x]
|
||||||
if w.Node != nil :
|
if w.node != nil :
|
||||||
clean(w)
|
clean(w)
|
||||||
return n
|
return n
|
||||||
dec(n.Count)
|
dec(n.count)
|
||||||
if n.Count > 0 :
|
if n.count > 0 :
|
||||||
for i in countup(x, n.Count -1) : n.slots[i] = n.slots[i + 1]
|
for i in countup(x, n.count -1) : n.slots[i] = n.slots[i + 1]
|
||||||
n.slots[n.Count] = nil
|
n.slots[n.count] = nil
|
||||||
case n.Count
|
case n.count
|
||||||
of cLen1 : setLen(n.slots, cLen1)
|
of cLen1 : setLen(n.slots, cLen1)
|
||||||
of cLen2 : setLen(n.slots, cLen2)
|
of cLen2 : setLen(n.slots, cLen2)
|
||||||
of cLen3 : setLen(n.slots, cLen3)
|
of cLen3 : setLen(n.slots, cLen3)
|
||||||
of cLenCenter : setLen(n.slots, cLenCenter)
|
of cLenCenter : setLen(n.slots, cLenCenter)
|
||||||
of cLen4 : setLen(n.slots, cLen4)
|
of cLen4 : setLen(n.slots, cLen4)
|
||||||
else: discard
|
else: discard
|
||||||
Result = n
|
result = n
|
||||||
|
|
||||||
else :
|
else :
|
||||||
Result = n.Left
|
result = n.left
|
||||||
n.slots = nil
|
n.slots = nil
|
||||||
n.Left = nil
|
n.left = nil
|
||||||
|
|
||||||
proc InternalDelete[T,D] (ANode: PNode[T,D], key: T, AValue: var D): PNode[T,D] =
|
proc internalDelete[T,D] (ANode: PNode[T,D], key: T, Avalue: var D): PNode[T,D] =
|
||||||
var Path: array[0..20, RPath[T,D]]
|
var Path: array[0..20, RPath[T,D]]
|
||||||
var n = ANode
|
var n = ANode
|
||||||
Result = n
|
result = n
|
||||||
clean(AValue)
|
clean(Avalue)
|
||||||
var h = 0
|
var h = 0
|
||||||
while n != nil:
|
while n != nil:
|
||||||
var x = bSearch(n, key)
|
var x = bSearch(n, key)
|
||||||
|
|
@ -119,17 +119,17 @@ proc InternalDelete[T,D] (ANode: PNode[T,D], key: T, AValue: var D): PNode[T,D]
|
||||||
Path[h].Xi = - x
|
Path[h].Xi = - x
|
||||||
inc(h)
|
inc(h)
|
||||||
if x == 0 :
|
if x == 0 :
|
||||||
n = n.Left
|
n = n.left
|
||||||
else :
|
else :
|
||||||
x = (-x) -1
|
x = (-x) -1
|
||||||
if x < n.Count :
|
if x < n.count :
|
||||||
n = n.slots[x].Node
|
n = n.slots[x].node
|
||||||
else :
|
else :
|
||||||
n = nil
|
n = nil
|
||||||
else :
|
else :
|
||||||
dec(x)
|
dec(x)
|
||||||
if isClean(n, x) : return
|
if isClean(n, x) : return
|
||||||
AValue = n.slots[x].Value
|
Avalue = n.slots[x].value
|
||||||
var n2 = DeleteItem(n, x)
|
var n2 = DeleteItem(n, x)
|
||||||
dec(h)
|
dec(h)
|
||||||
while (n2 != n) and (h >=0) :
|
while (n2 != n) and (h >=0) :
|
||||||
|
|
@ -139,30 +139,30 @@ proc InternalDelete[T,D] (ANode: PNode[T,D], key: T, AValue: var D): PNode[T,D]
|
||||||
if x >= 0 :
|
if x >= 0 :
|
||||||
if (n == nil) and isClean(w.Nd, x) :
|
if (n == nil) and isClean(w.Nd, x) :
|
||||||
n = w.Nd
|
n = w.Nd
|
||||||
n.slots[x].Node = nil
|
n.slots[x].node = nil
|
||||||
n2 = DeleteItem(n, x)
|
n2 = DeleteItem(n, x)
|
||||||
else :
|
else :
|
||||||
w.Nd.slots[x].Node = n
|
w.Nd.slots[x].node = n
|
||||||
return
|
return
|
||||||
else :
|
else :
|
||||||
w.Nd.Left = n
|
w.Nd.left = n
|
||||||
return
|
return
|
||||||
dec(h)
|
dec(h)
|
||||||
if h < 0:
|
if h < 0:
|
||||||
Result = n2
|
result = n2
|
||||||
return
|
return
|
||||||
|
|
||||||
proc InternalFind[T,D] (n: PNode[T,D], key: T): ref TItem[T,D] {.inline.} =
|
proc internalFind[T,D] (n: PNode[T,D], key: T): ref TItem[T,D] {.inline.} =
|
||||||
var wn = n
|
var wn = n
|
||||||
while wn != nil :
|
while wn != nil :
|
||||||
var x = bSearch(wn, key)
|
var x = bSearch(wn, key)
|
||||||
if x <= 0 :
|
if x <= 0 :
|
||||||
if x == 0 :
|
if x == 0 :
|
||||||
wn = wn.Left
|
wn = wn.left
|
||||||
else :
|
else :
|
||||||
x = (-x) -1
|
x = (-x) -1
|
||||||
if x < wn.Count :
|
if x < wn.count :
|
||||||
wn = wn.slots[x].Node
|
wn = wn.slots[x].node
|
||||||
else :
|
else :
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
|
@ -171,32 +171,32 @@ proc InternalFind[T,D] (n: PNode[T,D], key: T): ref TItem[T,D] {.inline.} =
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
proc traceTree[T,D](root: PNode[T,D]) =
|
proc traceTree[T,D](root: PNode[T,D]) =
|
||||||
proc traceX(x: Int) =
|
proc traceX(x: int) =
|
||||||
write stdout, "("
|
write stdout, "("
|
||||||
write stdout, x
|
write stdout, x
|
||||||
write stdout, ") "
|
write stdout, ") "
|
||||||
|
|
||||||
proc traceEl(el: ref TItem[T,D]) =
|
proc traceEl(el: ref TItem[T,D]) =
|
||||||
write stdout, " key: "
|
write stdout, " key: "
|
||||||
write stdout, el.Key
|
write stdout, el.key
|
||||||
write stdout, " value: "
|
write stdout, " value: "
|
||||||
write stdout, el.Value
|
write stdout, el.value
|
||||||
|
|
||||||
|
|
||||||
proc traceln(space: string) =
|
proc traceln(space: string) =
|
||||||
writeln stdout, ""
|
writeln stdout, ""
|
||||||
write stdout, space
|
write stdout, space
|
||||||
|
|
||||||
proc doTrace(n: PNode[T,D], level: Int) =
|
proc doTrace(n: PNode[T,D], level: int) =
|
||||||
var space = repeatChar(2 * level)
|
var space = repeatChar(2 * level)
|
||||||
traceln(space)
|
traceln(space)
|
||||||
write stdout, "node: "
|
write stdout, "node: "
|
||||||
if n == nil:
|
if n == nil:
|
||||||
writeln stdout, "is empty"
|
writeln stdout, "is empty"
|
||||||
return
|
return
|
||||||
write stdout, n.Count
|
write stdout, n.count
|
||||||
write stdout, " elements: "
|
write stdout, " elements: "
|
||||||
if n.Left != nil:
|
if n.left != nil:
|
||||||
traceln(space)
|
traceln(space)
|
||||||
write stdout, "left: "
|
write stdout, "left: "
|
||||||
doTrace(n.left, level +1)
|
doTrace(n.left, level +1)
|
||||||
|
|
@ -204,188 +204,188 @@ proc traceTree[T,D](root: PNode[T,D]) =
|
||||||
if el != nil and not isClean(el):
|
if el != nil and not isClean(el):
|
||||||
traceln(space)
|
traceln(space)
|
||||||
traceX(i)
|
traceX(i)
|
||||||
if i >= n.Count:
|
if i >= n.count:
|
||||||
write stdout, "error "
|
write stdout, "error "
|
||||||
else:
|
else:
|
||||||
traceEl(el)
|
traceEl(el)
|
||||||
if el.Node != nil: doTrace(el.Node, level +1)
|
if el.node != nil: doTrace(el.node, level +1)
|
||||||
else : write stdout, " empty "
|
else : write stdout, " empty "
|
||||||
elif i < n.Count :
|
elif i < n.count :
|
||||||
traceln(space)
|
traceln(space)
|
||||||
traceX(i)
|
traceX(i)
|
||||||
write stdout, "clean: "
|
write stdout, "clean: "
|
||||||
when T is string :
|
when T is string :
|
||||||
if el.Key != nil: write stdout, el.Key
|
if el.key != nil: write stdout, el.key
|
||||||
else : write stdout, el.Key
|
else : write stdout, el.key
|
||||||
if el.Node != nil: doTrace(el.Node, level +1)
|
if el.node != nil: doTrace(el.node, level +1)
|
||||||
else : write stdout, " empty "
|
else : write stdout, " empty "
|
||||||
writeln stdout,""
|
writeln stdout,""
|
||||||
|
|
||||||
doTrace(root, 0)
|
doTrace(root, 0)
|
||||||
|
|
||||||
proc InsertItem[T,D](APath: RPath[T,D], ANode:PNode[T,D], AKey: T, AValue: D) =
|
proc InsertItem[T,D](APath: RPath[T,D], ANode:PNode[T,D], Akey: T, Avalue: D) =
|
||||||
var x = - APath.Xi
|
var x = - APath.Xi
|
||||||
inc(APath.Nd.Count)
|
inc(APath.Nd.count)
|
||||||
case APath.Nd.Count
|
case APath.Nd.count
|
||||||
of cLen1: setLen(APath.Nd.slots, cLen2)
|
of cLen1: setLen(APath.Nd.slots, cLen2)
|
||||||
of cLen2: setLen(APath.Nd.slots, cLen3)
|
of cLen2: setLen(APath.Nd.slots, cLen3)
|
||||||
of cLen3: setLen(APath.Nd.slots, cLenCenter)
|
of cLen3: setLen(APath.Nd.slots, cLenCenter)
|
||||||
of cLenCenter: setLen(APath.Nd.slots, cLen4)
|
of cLenCenter: setLen(APath.Nd.slots, cLen4)
|
||||||
of cLen4: setLen(APath.Nd.slots, cLenMax)
|
of cLen4: setLen(APath.Nd.slots, cLenMax)
|
||||||
else: discard
|
else: discard
|
||||||
for i in countdown(APath.Nd.Count.int - 1, x + 1): shallowCopy(APath.Nd.slots[i], APath.Nd.slots[i - 1])
|
for i in countdown(APath.Nd.count.int - 1, x + 1): shallowCopy(APath.Nd.slots[i], APath.Nd.slots[i - 1])
|
||||||
APath.Nd.slots[x] = setItem(AKey, AValue, ANode)
|
APath.Nd.slots[x] = setItem(Akey, Avalue, ANode)
|
||||||
|
|
||||||
|
|
||||||
proc SplitPage[T,D](n, left: PNode[T,D], xi: Int, AKey:var T, AValue:var D): PNode[T,D] =
|
proc SplitPage[T,D](n, left: PNode[T,D], xi: int, Akey:var T, Avalue:var D): PNode[T,D] =
|
||||||
var x = -Xi
|
var x = -xi
|
||||||
var it1: TItems[T,D]
|
var it1: TItems[T,D]
|
||||||
it1.newSeq(cLenCenter)
|
it1.newSeq(cLenCenter)
|
||||||
new(Result)
|
new(result)
|
||||||
Result.slots.newSeq(cLenCenter)
|
result.slots.newSeq(cLenCenter)
|
||||||
Result.Count = cCenter
|
result.count = cCenter
|
||||||
if x == cCenter:
|
if x == cCenter:
|
||||||
for i in 0..cCenter -1: shallowCopy(it1[i], left.slots[i])
|
for i in 0..cCenter -1: shallowCopy(it1[i], left.slots[i])
|
||||||
for i in 0..cCenter -1: shallowCopy(Result.slots[i], left.slots[cCenter + i])
|
for i in 0..cCenter -1: shallowCopy(result.slots[i], left.slots[cCenter + i])
|
||||||
Result.Left = n
|
result.left = n
|
||||||
else :
|
else :
|
||||||
if x < cCenter :
|
if x < cCenter :
|
||||||
for i in 0..x-1: shallowCopy(it1[i], left.slots[i])
|
for i in 0..x-1: shallowCopy(it1[i], left.slots[i])
|
||||||
it1[x] = setItem(AKey, AValue, n)
|
it1[x] = setItem(Akey, Avalue, n)
|
||||||
for i in x+1 .. cCenter -1: shallowCopy(it1[i], left.slots[i-1])
|
for i in x+1 .. cCenter -1: shallowCopy(it1[i], left.slots[i-1])
|
||||||
var w = left.slots[cCenter -1]
|
var w = left.slots[cCenter -1]
|
||||||
AKey = w.Key
|
Akey = w.key
|
||||||
AValue = w.Value
|
Avalue = w.value
|
||||||
Result.Left = w.Node
|
result.left = w.node
|
||||||
for i in 0..cCenter -1: shallowCopy(Result.slots[i], left.slots[cCenter + i])
|
for i in 0..cCenter -1: shallowCopy(result.slots[i], left.slots[cCenter + i])
|
||||||
else :
|
else :
|
||||||
for i in 0..cCenter -1: shallowCopy(it1[i], left.slots[i])
|
for i in 0..cCenter -1: shallowCopy(it1[i], left.slots[i])
|
||||||
x = x - (cCenter + 1)
|
x = x - (cCenter + 1)
|
||||||
for i in 0..x-1: shallowCopy(Result.slots[i], left.slots[cCenter + i + 1])
|
for i in 0..x-1: shallowCopy(result.slots[i], left.slots[cCenter + i + 1])
|
||||||
Result.slots[x] = setItem(AKey, AValue, n)
|
result.slots[x] = setItem(Akey, Avalue, n)
|
||||||
for i in x+1 .. cCenter -1: shallowCopy(Result.slots[i], left.slots[cCenter + i])
|
for i in x+1 .. cCenter -1: shallowCopy(result.slots[i], left.slots[cCenter + i])
|
||||||
var w = left.slots[cCenter]
|
var w = left.slots[cCenter]
|
||||||
AKey = w.Key
|
Akey = w.key
|
||||||
AValue = w.Value
|
Avalue = w.value
|
||||||
Result.Left = w.Node
|
result.left = w.node
|
||||||
left.Count = cCenter
|
left.count = cCenter
|
||||||
shallowCopy(left.slots, it1)
|
shallowCopy(left.slots, it1)
|
||||||
|
|
||||||
|
|
||||||
proc InternalPut[T,D](ANode: ref TNode[T,D], AKey: T, AValue: D, OldValue: var D): ref TNode[T,D] =
|
proc internalPut[T,D](ANode: ref TNode[T,D], Akey: T, Avalue: D, Oldvalue: var D): ref TNode[T,D] =
|
||||||
var h: Int
|
var h: int
|
||||||
var Path: array[0..30, RPath[T,D]]
|
var Path: array[0..30, RPath[T,D]]
|
||||||
var left: PNode[T,D]
|
var left: PNode[T,D]
|
||||||
var n = ANode
|
var n = ANode
|
||||||
|
|
||||||
|
|
||||||
Result = ANode
|
result = ANode
|
||||||
h = 0
|
h = 0
|
||||||
while n != nil:
|
while n != nil:
|
||||||
var x = bSearch[T,D](n, AKey)
|
var x = bSearch[T,D](n, Akey)
|
||||||
if x <= 0 :
|
if x <= 0 :
|
||||||
Path[h].Nd = n
|
Path[h].Nd = n
|
||||||
Path[h].Xi = x
|
Path[h].Xi = x
|
||||||
inc(h)
|
inc(h)
|
||||||
if x == 0 :
|
if x == 0 :
|
||||||
n = n.Left
|
n = n.left
|
||||||
else :
|
else :
|
||||||
x = (-x) -1
|
x = (-x) -1
|
||||||
if x < n.Count :
|
if x < n.count :
|
||||||
n = n.slots[x].Node
|
n = n.slots[x].node
|
||||||
else :
|
else :
|
||||||
n = nil
|
n = nil
|
||||||
else :
|
else :
|
||||||
var w = n.slots[x - 1]
|
var w = n.slots[x - 1]
|
||||||
OldValue = w.Value
|
Oldvalue = w.value
|
||||||
w.Value = AValue
|
w.value = Avalue
|
||||||
return
|
return
|
||||||
|
|
||||||
dec(h)
|
dec(h)
|
||||||
left = nil
|
left = nil
|
||||||
var lKey = AKey
|
var lkey = Akey
|
||||||
var lValue = AValue
|
var lvalue = Avalue
|
||||||
while h >= 0 :
|
while h >= 0 :
|
||||||
if Path[h].Nd.Count < cLenMax :
|
if Path[h].Nd.count < cLenMax :
|
||||||
InsertItem(Path[h], n, lKey, lValue)
|
InsertItem(Path[h], n, lkey, lvalue)
|
||||||
return
|
return
|
||||||
else :
|
else :
|
||||||
left = Path[h].Nd
|
left = Path[h].Nd
|
||||||
n = SplitPage(n, left, Path[h].Xi, lKey, lValue)
|
n = SplitPage(n, left, Path[h].Xi, lkey, lvalue)
|
||||||
dec(h)
|
dec(h)
|
||||||
|
|
||||||
new(Result)
|
new(result)
|
||||||
Result.slots.newSeq(cLen1)
|
result.slots.newSeq(cLen1)
|
||||||
Result.Count = 1
|
result.count = 1
|
||||||
Result.Left = left
|
result.left = left
|
||||||
Result.slots[0] = setItem(lKey, lValue, n)
|
result.slots[0] = setItem(lkey, lvalue, n)
|
||||||
|
|
||||||
|
|
||||||
proc CleanTree[T,D](n: PNode[T,D]): PNode[T,D] =
|
proc CleanTree[T,D](n: PNode[T,D]): PNode[T,D] =
|
||||||
if n.Left != nil :
|
if n.left != nil :
|
||||||
n.Left = CleanTree(n.Left)
|
n.left = CleanTree(n.left)
|
||||||
for i in 0 .. n.Count - 1 :
|
for i in 0 .. n.count - 1 :
|
||||||
var w = n.slots[i]
|
var w = n.slots[i]
|
||||||
if w.Node != nil :
|
if w.node != nil :
|
||||||
w.Node = CleanTree(w.Node)
|
w.node = CleanTree(w.node)
|
||||||
clean(w.Value)
|
clean(w.value)
|
||||||
clean(w.Key)
|
clean(w.key)
|
||||||
n.slots = nil
|
n.slots = nil
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
|
||||||
proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]): PNode[T,D] {.closure.} ): PNode[T,D] =
|
proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]): PNode[T,D] {.closure.} ): PNode[T,D] =
|
||||||
if n != nil :
|
if n != nil :
|
||||||
if n.Left != nil :
|
if n.left != nil :
|
||||||
n.Left = VisitAllNodes(n.Left, visit)
|
n.left = VisitAllNodes(n.left, visit)
|
||||||
for i in 0 .. n.Count - 1 :
|
for i in 0 .. n.count - 1 :
|
||||||
var w = n.slots[i]
|
var w = n.slots[i]
|
||||||
if w.Node != nil :
|
if w.node != nil :
|
||||||
w.Node = VisitAllNodes(w.Node, visit)
|
w.node = VisitAllNodes(w.node, visit)
|
||||||
return visit(n)
|
return visit(n)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]) {.closure.} ) =
|
proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]) {.closure.} ) =
|
||||||
if n != nil:
|
if n != nil:
|
||||||
if n.Left != nil :
|
if n.left != nil :
|
||||||
VisitAllNodes(n.Left, visit)
|
VisitAllNodes(n.left, visit)
|
||||||
for i in 0 .. n.Count - 1 :
|
for i in 0 .. n.count - 1 :
|
||||||
var w = n.slots[i]
|
var w = n.slots[i]
|
||||||
if w.Node != nil :
|
if w.node != nil :
|
||||||
VisitAllNodes(w.Node, visit)
|
VisitAllNodes(w.node, visit)
|
||||||
visit(n)
|
visit(n)
|
||||||
|
|
||||||
proc VisitAll[T,D](n: PNode[T,D], visit: proc(AKey: T, AValue: D) {.closure.} ) =
|
proc VisitAll[T,D](n: PNode[T,D], visit: proc(Akey: T, Avalue: D) {.closure.} ) =
|
||||||
if n != nil:
|
if n != nil:
|
||||||
if n.Left != nil :
|
if n.left != nil :
|
||||||
VisitAll(n.Left, visit)
|
VisitAll(n.left, visit)
|
||||||
for i in 0 .. n.Count - 1 :
|
for i in 0 .. n.count - 1 :
|
||||||
var w = n.slots[i]
|
var w = n.slots[i]
|
||||||
if not w.isClean :
|
if not w.isClean :
|
||||||
visit(w.Key, w.Value)
|
visit(w.key, w.value)
|
||||||
if w.Node != nil :
|
if w.node != nil :
|
||||||
VisitAll(w.Node, visit)
|
VisitAll(w.node, visit)
|
||||||
|
|
||||||
proc VisitAll[T,D](n: PNode[T,D], visit: proc(AKey: T, AValue: var D):Bool {.closure.} ): PNode[T,D] =
|
proc VisitAll[T,D](n: PNode[T,D], visit: proc(Akey: T, Avalue: var D):bool {.closure.} ): PNode[T,D] =
|
||||||
if n != nil:
|
if n != nil:
|
||||||
var n1 = n.Left
|
var n1 = n.left
|
||||||
if n1 != nil :
|
if n1 != nil :
|
||||||
var n2 = VisitAll(n1, visit)
|
var n2 = VisitAll(n1, visit)
|
||||||
if n1 != n2 :
|
if n1 != n2 :
|
||||||
n.Left = n2
|
n.left = n2
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < n.Count :
|
while i < n.count :
|
||||||
var w = n.slots[i]
|
var w = n.slots[i]
|
||||||
if not w.isClean :
|
if not w.isClean :
|
||||||
if visit(w.Key, w.Value) :
|
if visit(w.key, w.value) :
|
||||||
Result = DeleteItem(n, i)
|
result = DeleteItem(n, i)
|
||||||
if Result == nil : return
|
if result == nil : return
|
||||||
dec(i)
|
dec(i)
|
||||||
n1 = w.Node
|
n1 = w.node
|
||||||
if n1 != nil :
|
if n1 != nil :
|
||||||
var n2 = VisitAll(n1, visit)
|
var n2 = VisitAll(n1, visit)
|
||||||
if n1 != n2 :
|
if n1 != n2 :
|
||||||
w.Node = n2
|
w.node = n2
|
||||||
inc(i)
|
inc(i)
|
||||||
return n
|
return n
|
||||||
|
|
||||||
|
|
@ -396,20 +396,20 @@ iterator keys* [T,D] (n: PNode[T,D]): T =
|
||||||
var nd = n
|
var nd = n
|
||||||
var i = -1
|
var i = -1
|
||||||
while true :
|
while true :
|
||||||
if i < nd.Count :
|
if i < nd.count :
|
||||||
Path[level].Nd = nd
|
Path[level].Nd = nd
|
||||||
Path[level].Xi = i
|
Path[level].Xi = i
|
||||||
if i < 0 :
|
if i < 0 :
|
||||||
if nd.Left != nil :
|
if nd.left != nil :
|
||||||
nd = nd.Left
|
nd = nd.left
|
||||||
inc(level)
|
inc(level)
|
||||||
else : inc(i)
|
else : inc(i)
|
||||||
else :
|
else :
|
||||||
var w = nd.slots[i]
|
var w = nd.slots[i]
|
||||||
if not w.isClean() :
|
if not w.isClean() :
|
||||||
yield w.Key
|
yield w.key
|
||||||
if w.Node != nil :
|
if w.node != nil :
|
||||||
nd = w.Node
|
nd = w.node
|
||||||
i = -1
|
i = -1
|
||||||
inc(level)
|
inc(level)
|
||||||
else : inc(i)
|
else : inc(i)
|
||||||
|
|
@ -424,22 +424,22 @@ iterator keys* [T,D] (n: PNode[T,D]): T =
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
|
|
||||||
proc test() =
|
proc test() =
|
||||||
var oldValue: Int
|
var oldvalue: int
|
||||||
var root = InternalPut[int, int](nil, 312, 312, oldValue)
|
var root = internalPut[int, int](nil, 312, 312, oldvalue)
|
||||||
var someOtherRoot = InternalPut[string, int](nil, "312", 312, oldValue)
|
var someOtherRoot = internalPut[string, int](nil, "312", 312, oldvalue)
|
||||||
var it1 = InternalFind(root, 312)
|
var it1 = internalFind(root, 312)
|
||||||
echo it1.Value
|
echo it1.value
|
||||||
|
|
||||||
for i in 1..1_000_000:
|
for i in 1..1_000_000:
|
||||||
root = InternalPut(root, i, i, oldValue)
|
root = internalPut(root, i, i, oldvalue)
|
||||||
|
|
||||||
var cnt = 0
|
var cnt = 0
|
||||||
oldValue = -1
|
oldvalue = -1
|
||||||
when true : # code compiles, when this or the other when is switched to false
|
when true : # code compiles, when this or the other when is switched to false
|
||||||
for k in root.keys :
|
for k in root.keys :
|
||||||
if k <= oldValue :
|
if k <= oldvalue :
|
||||||
echo k
|
echo k
|
||||||
oldValue = k
|
oldvalue = k
|
||||||
inc(cnt)
|
inc(cnt)
|
||||||
echo cnt
|
echo cnt
|
||||||
when true :
|
when true :
|
||||||
|
|
@ -450,21 +450,21 @@ when isMainModule:
|
||||||
root = VisitAll(root, proc(key: int, value: var int): bool =
|
root = VisitAll(root, proc(key: int, value: var int): bool =
|
||||||
return key mod 2 == 0 )
|
return key mod 2 == 0 )
|
||||||
cnt = 0
|
cnt = 0
|
||||||
oldValue = -1
|
oldvalue = -1
|
||||||
VisitAll(root, proc(key: int, value: int) {.closure.} =
|
VisitAll(root, proc(key: int, value: int) {.closure.} =
|
||||||
if key <= oldValue :
|
if key <= oldvalue :
|
||||||
echo key
|
echo key
|
||||||
oldValue = key
|
oldvalue = key
|
||||||
inc(cnt) )
|
inc(cnt) )
|
||||||
echo cnt
|
echo cnt
|
||||||
root = VisitAll(root, proc(key: int, value: var int): bool =
|
root = VisitAll(root, proc(key: int, value: var int): bool =
|
||||||
return key mod 2 != 0 )
|
return key mod 2 != 0 )
|
||||||
cnt = 0
|
cnt = 0
|
||||||
oldValue = -1
|
oldvalue = -1
|
||||||
VisitAll(root, proc(key: int, value: int) {.closure.} =
|
VisitAll(root, proc(key: int, value: int) {.closure.} =
|
||||||
if key <= oldValue :
|
if key <= oldvalue :
|
||||||
echo "error ", key
|
echo "error ", key
|
||||||
oldValue = key
|
oldvalue = key
|
||||||
inc(cnt) )
|
inc(cnt) )
|
||||||
echo cnt
|
echo cnt
|
||||||
#traceTree(root)
|
#traceTree(root)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ proc filter[T,D](data: seq[T], env:D, pred: TFilterProc[T,D]): seq[T] =
|
||||||
for e in data:
|
for e in data:
|
||||||
if pred(e, env): result.add(e)
|
if pred(e, env): result.add(e)
|
||||||
|
|
||||||
proc predTest(item: int, value: int): Bool =
|
proc predTest(item: int, value: int): bool =
|
||||||
return item <= value
|
return item <= value
|
||||||
|
|
||||||
proc test(data: seq[int], value: int): seq[int] =
|
proc test(data: seq[int], value: int): seq[int] =
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
type
|
type
|
||||||
TMaybe[T] = object
|
TMaybe[T] = object
|
||||||
case empty: Bool
|
case empty: bool
|
||||||
of False: value: T
|
of false: value: T
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc Just*[T](val: T): TMaybe[T] =
|
proc Just*[T](val: T): TMaybe[T] =
|
||||||
result.empty = False
|
result.empty = false
|
||||||
result.value = val
|
result.value = val
|
||||||
|
|
||||||
proc Nothing[T](): TMaybe[T] =
|
proc Nothing[T](): TMaybe[T] =
|
||||||
result.empty = True
|
result.empty = true
|
||||||
|
|
||||||
proc safeReadLine(): TMaybe[string] =
|
proc safeReadLine(): TMaybe[string] =
|
||||||
var r = stdin.readLine()
|
var r = stdin.readLine()
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ block Test1:
|
||||||
# a non-generic iterator!
|
# a non-generic iterator!
|
||||||
|
|
||||||
var t = initTable[int, string]()
|
var t = initTable[int, string]()
|
||||||
for k, v in t.pairs: nil
|
for k, v in t.pairs: discard
|
||||||
for k, v in t.pairs: nil
|
for k, v in t.pairs: discard
|
||||||
|
|
||||||
echo "true"
|
echo "true"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,13 @@ iterator tokenize2(s: string, seps: set[char] = Whitespace): tuple[
|
||||||
yield (substr(s, i, j-1), false)
|
yield (substr(s, i, j-1), false)
|
||||||
i = j
|
i = j
|
||||||
|
|
||||||
for word, isSep in tokenize2("ta da", whiteSpace):
|
for word, isSep in tokenize2("ta da", WhiteSpace):
|
||||||
var titer2TestVar = 0
|
var titer2TestVar = 0
|
||||||
stdout.write(titer2TestVar)
|
stdout.write(titer2TestVar)
|
||||||
|
|
||||||
proc wordWrap2(s: string, maxLineWidth = 80,
|
proc wordWrap2(s: string, maxLineWidth = 80,
|
||||||
splitLongWords = true,
|
splitLongWords = true,
|
||||||
seps: set[char] = whitespace,
|
seps: set[char] = Whitespace,
|
||||||
newLine = "\n"): string =
|
newLine = "\n"): string =
|
||||||
result = ""
|
result = ""
|
||||||
for word, isSep in tokenize2(s, seps):
|
for word, isSep in tokenize2(s, seps):
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ iterator count3(): int {.closure.} =
|
||||||
yield 2
|
yield 2
|
||||||
yield 3
|
yield 3
|
||||||
|
|
||||||
for word, isSep in tokenize2("ta da", whiteSpace):
|
for word, isSep in tokenize2("ta da", WhiteSpace):
|
||||||
if not isSep:
|
if not isSep:
|
||||||
stdout.write(word)
|
stdout.write(word)
|
||||||
echo ""
|
echo ""
|
||||||
|
|
@ -56,7 +56,7 @@ proc inProc() =
|
||||||
for c in count3():
|
for c in count3():
|
||||||
echo c
|
echo c
|
||||||
|
|
||||||
for word, isSep in tokenize2("ta da", whiteSpace):
|
for word, isSep in tokenize2("ta da", WhiteSpace):
|
||||||
stdout.write(word)
|
stdout.write(word)
|
||||||
|
|
||||||
for c in count3():
|
for c in count3():
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ discard """
|
||||||
output: '''x: 0 y: 0'''
|
output: '''x: 0 y: 0'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc ToString*[T](x: T): string = return $x
|
proc toString*[T](x: T): string = return $x
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import
|
||||||
proc main() =
|
proc main() =
|
||||||
var
|
var
|
||||||
a, b: TTime
|
a, b: TTime
|
||||||
a = getLastModificationTime(ParamStr(1))
|
a = getLastModificationTime(paramStr(1))
|
||||||
b = getLastModificationTime(ParamStr(2))
|
b = getLastModificationTime(paramStr(2))
|
||||||
writeln(stdout, $a)
|
writeln(stdout, $a)
|
||||||
writeln(stdout, $b)
|
writeln(stdout, $b)
|
||||||
if a < b:
|
if a < b:
|
||||||
Write(stdout, "$2 is newer than $1\n" % [ParamStr(1), ParamStr(2)])
|
write(stdout, "$2 is newer than $1\n" % [paramStr(1), paramStr(2)])
|
||||||
else:
|
else:
|
||||||
Write(stdout, "$1 is newer than $2\n" % [ParamStr(1), ParamStr(2)])
|
write(stdout, "$1 is newer than $2\n" % [paramStr(1), paramStr(2)])
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ proc TestLoops() =
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
|
|
||||||
while True:
|
while true:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@ discard """
|
||||||
"""
|
"""
|
||||||
# BUG: following compiles, but should not:
|
# BUG: following compiles, but should not:
|
||||||
|
|
||||||
proc nodeOfDegree(x: Int): bool =
|
proc nodeOfDegree(x: int): bool =
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc main =
|
proc main =
|
||||||
for j in 0..2:
|
for j in 0..2:
|
||||||
for i in 0..10:
|
for i in 0..10:
|
||||||
if not nodeOfDegree(1) >= 0: #ERROR_MSG type mismatch
|
if not nodeOfDegree(1) >= 0: #ERROR_MSG type mismatch
|
||||||
Echo "Yes"
|
echo "Yes"
|
||||||
else:
|
else:
|
||||||
Echo "No"
|
echo "No"
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ proc mypos(sub, s: string, start: int = 0): int =
|
||||||
if i >= N:
|
if i >= N:
|
||||||
result = -1
|
result = -1
|
||||||
else:
|
else:
|
||||||
while True:
|
while true:
|
||||||
if s[i] == sub[j]:
|
if s[i] == sub[j]:
|
||||||
Inc(i)
|
inc(i)
|
||||||
Inc(j)
|
inc(j)
|
||||||
else:
|
else:
|
||||||
i = i - j + 1
|
i = i - j + 1
|
||||||
j = 0
|
j = 0
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ else:
|
||||||
|
|
||||||
var
|
var
|
||||||
s: string
|
s: string
|
||||||
write(stdout, "compiled at " & system.compileDate &
|
write(stdout, "compiled at " & system.CompileDate &
|
||||||
" " & compileTime & "\n")
|
" " & CompileTime & "\n")
|
||||||
echo getDateStr()
|
echo getDateStr()
|
||||||
echo getClockStr()
|
echo getClockStr()
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
## We use a radix tree with node compression.
|
## We use a radix tree with node compression.
|
||||||
## There are two node kinds:
|
## There are two node kinds:
|
||||||
|
|
||||||
const bitsPerUnit = 8*sizeof(int)
|
const BitsPerUnit = 8*sizeof(int)
|
||||||
|
|
||||||
type
|
type
|
||||||
TRadixNodeKind = enum rnLinear, rnFull, rnLeafBits, rnLeafLinear
|
TRadixNodeKind = enum rnLinear, rnFull, rnLeafBits, rnLeafLinear
|
||||||
|
|
@ -42,13 +42,13 @@ proc testBit(w, i: int): bool {.inline.} =
|
||||||
result = (w and (1 shl (i %% BitsPerUnit))) != 0
|
result = (w and (1 shl (i %% BitsPerUnit))) != 0
|
||||||
|
|
||||||
proc setBit(w: var int, i: int) {.inline.} =
|
proc setBit(w: var int, i: int) {.inline.} =
|
||||||
w = w or (1 shl (i %% bitsPerUnit))
|
w = w or (1 shl (i %% BitsPerUnit))
|
||||||
|
|
||||||
proc resetBit(w: var int, i: int) {.inline.} =
|
proc resetBit(w: var int, i: int) {.inline.} =
|
||||||
w = w and not (1 shl (i %% bitsPerUnit))
|
w = w and not (1 shl (i %% BitsPerUnit))
|
||||||
|
|
||||||
proc testOrSetBit(w: var int, i: int): bool {.inline.} =
|
proc testOrSetBit(w: var int, i: int): bool {.inline.} =
|
||||||
var x = (1 shl (i %% bitsPerUnit))
|
var x = (1 shl (i %% BitsPerUnit))
|
||||||
if (w and x) != 0: return true
|
if (w and x) != 0: return true
|
||||||
w = w or x
|
w = w or x
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ proc exclLeaf(r: PRadixNode, a: int) =
|
||||||
return
|
return
|
||||||
else: assert(false)
|
else: assert(false)
|
||||||
|
|
||||||
proc contains*(r: PRadixNode, a: TAddress): bool =
|
proc contains*(r: PRadixNode, a: ByteAddress): bool =
|
||||||
if r == nil: return false
|
if r == nil: return false
|
||||||
var x = searchInner(r, a shr 24 and 0xff)
|
var x = searchInner(r, a shr 24 and 0xff)
|
||||||
if x == nil: return false
|
if x == nil: return false
|
||||||
|
|
@ -88,7 +88,7 @@ proc contains*(r: PRadixNode, a: TAddress): bool =
|
||||||
if x == nil: return false
|
if x == nil: return false
|
||||||
return searchLeaf(x, a and 0xff)
|
return searchLeaf(x, a and 0xff)
|
||||||
|
|
||||||
proc excl*(r: PRadixNode, a: TAddress): bool =
|
proc excl*(r: PRadixNode, a: ByteAddress): bool =
|
||||||
if r == nil: return false
|
if r == nil: return false
|
||||||
var x = searchInner(r, a shr 24 and 0xff)
|
var x = searchInner(r, a shr 24 and 0xff)
|
||||||
if x == nil: return false
|
if x == nil: return false
|
||||||
|
|
@ -167,10 +167,10 @@ proc addInner(r: var PRadixNode, a: int, d: int): bool =
|
||||||
return addInner(x.b[k], a, d-8)
|
return addInner(x.b[k], a, d-8)
|
||||||
else: assert(false)
|
else: assert(false)
|
||||||
|
|
||||||
proc incl*(r: var PRadixNode, a: TAddress) {.inline.} =
|
proc incl*(r: var PRadixNode, a: ByteAddress) {.inline.} =
|
||||||
discard addInner(r, a, 24)
|
discard addInner(r, a, 24)
|
||||||
|
|
||||||
proc testOrIncl*(r: var PRadixNode, a: TAddress): bool {.inline.} =
|
proc testOrIncl*(r: var PRadixNode, a: ByteAddress): bool {.inline.} =
|
||||||
return addInner(r, a, 24)
|
return addInner(r, a, 24)
|
||||||
|
|
||||||
iterator innerElements(r: PRadixNode): tuple[prefix: int, n: PRadixNode] =
|
iterator innerElements(r: PRadixNode): tuple[prefix: int, n: PRadixNode] =
|
||||||
|
|
@ -204,7 +204,7 @@ iterator leafElements(r: PRadixNode): int =
|
||||||
yield ze(r.keys[i])
|
yield ze(r.keys[i])
|
||||||
else: assert(false)
|
else: assert(false)
|
||||||
|
|
||||||
iterator elements*(r: PRadixNode): TAddress {.inline.} =
|
iterator elements*(r: PRadixNode): ByteAddress {.inline.} =
|
||||||
for p1, n1 in innerElements(r):
|
for p1, n1 in innerElements(r):
|
||||||
for p2, n2 in innerElements(n1):
|
for p2, n2 in innerElements(n1):
|
||||||
for p3, n3 in innerElements(n2):
|
for p3, n3 in innerElements(n2):
|
||||||
|
|
@ -297,7 +297,7 @@ when false:
|
||||||
result = ze(r.keys[i.x])
|
result = ze(r.keys[i.x])
|
||||||
inc(i.x)
|
inc(i.x)
|
||||||
|
|
||||||
iterator elements(r: PRadixNode): TAddress {.inline.} =
|
iterator elements(r: PRadixNode): ByteAddress {.inline.} =
|
||||||
var
|
var
|
||||||
a, b, c, d: TRadixIter
|
a, b, c, d: TRadixIter
|
||||||
init(a, r)
|
init(a, r)
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
# Macintosh, Unix or Windows text format.
|
# Macintosh, Unix or Windows text format.
|
||||||
|
|
||||||
var
|
var
|
||||||
inp: TFile
|
inp: File
|
||||||
line: string
|
line: string
|
||||||
|
|
||||||
if open(inp, "readme.txt"):
|
if open(inp, "readme.txt"):
|
||||||
while not EndOfFile(inp):
|
while not endOfFile(inp):
|
||||||
line = readLine(inp)
|
line = readLine(inp)
|
||||||
echo("#" & line & "#")
|
echo("#" & line & "#")
|
||||||
close(inp)
|
close(inp)
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,6 @@ discard """
|
||||||
|
|
||||||
import hashes, math
|
import hashes, math
|
||||||
|
|
||||||
|
|
||||||
when defined(shallowADT):
|
|
||||||
{.pragma: myShallow, shallow.}
|
|
||||||
else:
|
|
||||||
{.pragma: myShallow.}
|
{.pragma: myShallow.}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -63,7 +59,7 @@ template rawInsertImpl() =
|
||||||
data[h].val = val
|
data[h].val = val
|
||||||
data[h].slot = seFilled
|
data[h].slot = seFilled
|
||||||
|
|
||||||
proc RawGet[A, B](t: TTable[A, B], key: A): int =
|
proc rawGet[A, B](t: TTable[A, B], key: A): int =
|
||||||
rawGetImpl()
|
rawGetImpl()
|
||||||
|
|
||||||
proc `[]`*[A, B](t: TTable[A, B], key: A): B =
|
proc `[]`*[A, B](t: TTable[A, B], key: A): B =
|
||||||
|
|
@ -71,31 +67,31 @@ proc `[]`*[A, B](t: TTable[A, B], key: A): B =
|
||||||
## default empty value for the type `B` is returned
|
## default empty value for the type `B` is returned
|
||||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||||
## exists.
|
## exists.
|
||||||
var index = RawGet(t, key)
|
var index = rawGet(t, key)
|
||||||
if index >= 0: result = t.data[index].val
|
if index >= 0: result = t.data[index].val
|
||||||
|
|
||||||
proc hasKey*[A, B](t: TTable[A, B], key: A): bool =
|
proc hasKey*[A, B](t: TTable[A, B], key: A): bool =
|
||||||
## returns true iff `key` is in the table `t`.
|
## returns true iff `key` is in the table `t`.
|
||||||
result = rawGet(t, key) >= 0
|
result = rawGet(t, key) >= 0
|
||||||
|
|
||||||
proc RawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B],
|
proc rawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B],
|
||||||
key: A, val: B) =
|
key: A, val: B) =
|
||||||
rawInsertImpl()
|
rawInsertImpl()
|
||||||
|
|
||||||
proc Enlarge[A, B](t: var TTable[A, B]) =
|
proc enlarge[A, B](t: var TTable[A, B]) =
|
||||||
var n: TKeyValuePairSeq[A, B]
|
var n: TKeyValuePairSeq[A, B]
|
||||||
newSeq(n, len(t.data) * growthFactor)
|
newSeq(n, len(t.data) * growthFactor)
|
||||||
for i in countup(0, high(t.data)):
|
for i in countup(0, high(t.data)):
|
||||||
if t.data[i].slot == seFilled: RawInsert(t, n, t.data[i].key, t.data[i].val)
|
if t.data[i].slot == seFilled: rawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||||
swap(t.data, n)
|
swap(t.data, n)
|
||||||
|
|
||||||
template PutImpl() =
|
template putImpl() =
|
||||||
var index = RawGet(t, key)
|
var index = rawGet(t, key)
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
t.data[index].val = val
|
t.data[index].val = val
|
||||||
else:
|
else:
|
||||||
if mustRehash(len(t.data), t.counter): Enlarge(t)
|
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||||
RawInsert(t, t.data, key, val)
|
rawInsert(t, t.data, key, val)
|
||||||
inc(t.counter)
|
inc(t.counter)
|
||||||
|
|
||||||
proc `[]=`*[A, B](t: var TTable[A, B], key: A, val: B) =
|
proc `[]=`*[A, B](t: var TTable[A, B], key: A, val: B) =
|
||||||
|
|
@ -104,7 +100,7 @@ proc `[]=`*[A, B](t: var TTable[A, B], key: A, val: B) =
|
||||||
|
|
||||||
proc del*[A, B](t: var TTable[A, B], key: A) =
|
proc del*[A, B](t: var TTable[A, B], key: A) =
|
||||||
## deletes `key` from hash table `t`.
|
## deletes `key` from hash table `t`.
|
||||||
var index = RawGet(t, key)
|
var index = rawGet(t, key)
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
t.data[index].slot = seDeleted
|
t.data[index].slot = seDeleted
|
||||||
dec(t.counter)
|
dec(t.counter)
|
||||||
|
|
@ -183,24 +179,24 @@ proc hasKey*[A](t: TCountTable[A], key: A): bool =
|
||||||
## returns true iff `key` is in the table `t`.
|
## returns true iff `key` is in the table `t`.
|
||||||
result = rawGet(t, key) >= 0
|
result = rawGet(t, key) >= 0
|
||||||
|
|
||||||
proc RawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]],
|
proc rawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]],
|
||||||
key: A, val: int) =
|
key: A, val: int) =
|
||||||
var h: THash = hash(key) and high(data)
|
var h: THash = hash(key) and high(data)
|
||||||
while data[h].val != 0: h = nextTry(h, high(data))
|
while data[h].val != 0: h = nextTry(h, high(data))
|
||||||
data[h].key = key
|
data[h].key = key
|
||||||
data[h].val = val
|
data[h].val = val
|
||||||
|
|
||||||
proc Enlarge[A](t: var TCountTable[A]) =
|
proc enlarge[A](t: var TCountTable[A]) =
|
||||||
var n: seq[tuple[key: A, val: int]]
|
var n: seq[tuple[key: A, val: int]]
|
||||||
newSeq(n, len(t.data) * growthFactor)
|
newSeq(n, len(t.data) * growthFactor)
|
||||||
for i in countup(0, high(t.data)):
|
for i in countup(0, high(t.data)):
|
||||||
if t.data[i].val != 0: RawInsert(t, n, t.data[i].key, t.data[i].val)
|
if t.data[i].val != 0: rawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||||
swap(t.data, n)
|
swap(t.data, n)
|
||||||
|
|
||||||
proc `[]=`*[A](t: var TCountTable[A], key: A, val: int) =
|
proc `[]=`*[A](t: var TCountTable[A], key: A, val: int) =
|
||||||
## puts a (key, value)-pair into `t`. `val` has to be positive.
|
## puts a (key, value)-pair into `t`. `val` has to be positive.
|
||||||
assert val > 0
|
assert val > 0
|
||||||
PutImpl()
|
putImpl()
|
||||||
|
|
||||||
proc initCountTable*[A](initialSize=64): TCountTable[A] =
|
proc initCountTable*[A](initialSize=64): TCountTable[A] =
|
||||||
## creates a new count table that is empty. `initialSize` needs to be
|
## creates a new count table that is empty. `initialSize` needs to be
|
||||||
|
|
@ -224,11 +220,11 @@ proc inc*[A](t: var TCountTable[A], key: A, val = 1) =
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
inc(t.data[index].val, val)
|
inc(t.data[index].val, val)
|
||||||
else:
|
else:
|
||||||
if mustRehash(len(t.data), t.counter): Enlarge(t)
|
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||||
RawInsert(t, t.data, key, val)
|
rawInsert(t, t.data, key, val)
|
||||||
inc(t.counter)
|
inc(t.counter)
|
||||||
|
|
||||||
proc Smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
proc smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||||
## returns the largest (key,val)-pair. Efficiency: O(n)
|
## returns the largest (key,val)-pair. Efficiency: O(n)
|
||||||
assert t.len > 0
|
assert t.len > 0
|
||||||
var minIdx = 0
|
var minIdx = 0
|
||||||
|
|
@ -237,7 +233,7 @@ proc Smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||||
result.key = t.data[minIdx].key
|
result.key = t.data[minIdx].key
|
||||||
result.val = t.data[minIdx].val
|
result.val = t.data[minIdx].val
|
||||||
|
|
||||||
proc Largest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
proc largest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||||
## returns the (key,val)-pair with the largest `val`. Efficiency: O(n)
|
## returns the (key,val)-pair with the largest `val`. Efficiency: O(n)
|
||||||
assert t.len > 0
|
assert t.len > 0
|
||||||
var maxIdx = 0
|
var maxIdx = 0
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ proc toNum(b: TBuffer): int32 =
|
||||||
while (ze(b[i]) and 128) != 0:
|
while (ze(b[i]) and 128) != 0:
|
||||||
inc(i)
|
inc(i)
|
||||||
result = result or ((int32(ze(b[i])) and 127'i32) shl Shift)
|
result = result or ((int32(ze(b[i])) and 127'i32) shl Shift)
|
||||||
Shift = shift + 7'i32
|
Shift = Shift + 7'i32
|
||||||
if (ze(b[0]) and (1 shl 6)) != 0: # sign bit set?
|
if (ze(b[0]) and (1 shl 6)) != 0: # sign bit set?
|
||||||
result = (not result) +% 1'i32
|
result = (not result) +% 1'i32
|
||||||
# this is the same as ``- result``
|
# this is the same as ``- result``
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ some(10)'''
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
type Option[A] = object
|
type Option[A] = object
|
||||||
case isDefined*: Bool
|
case isDefined*: bool
|
||||||
of true:
|
of true:
|
||||||
value*: A
|
value*: A
|
||||||
of false:
|
of false:
|
||||||
|
|
@ -19,7 +19,7 @@ proc some[A](value: A): Option[A] =
|
||||||
proc none[A](): Option[A] =
|
proc none[A](): Option[A] =
|
||||||
Option[A](isDefined: false)
|
Option[A](isDefined: false)
|
||||||
|
|
||||||
proc `$`[A](o: Option[A]): String =
|
proc `$`[A](o: Option[A]): string =
|
||||||
if o.isDefined:
|
if o.isDefined:
|
||||||
"some($1)" % [$o.value]
|
"some($1)" % [$o.value]
|
||||||
else:
|
else:
|
||||||
|
|
@ -27,14 +27,14 @@ proc `$`[A](o: Option[A]): String =
|
||||||
|
|
||||||
let x = some("str")
|
let x = some("str")
|
||||||
let y = some(5)
|
let y = some(5)
|
||||||
let z = none[Int]()
|
let z = none[int]()
|
||||||
|
|
||||||
echo x, ", ", y, ", ", z
|
echo x, ", ", y, ", ", z
|
||||||
|
|
||||||
proc intOrString[A : Int | String](o: Option[A]): Option[A] =
|
proc intOrString[A : int | string](o: Option[A]): Option[A] =
|
||||||
when A is Int:
|
when A is int:
|
||||||
some(o.value + 5)
|
some(o.value + 5)
|
||||||
elif A is String:
|
elif A is string:
|
||||||
some(o.value & "!")
|
some(o.value & "!")
|
||||||
else:
|
else:
|
||||||
o
|
o
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ a = high(int)
|
||||||
b = -2
|
b = -2
|
||||||
try:
|
try:
|
||||||
writeln(stdout, b - a)
|
writeln(stdout, b - a)
|
||||||
except EOverflow:
|
except OverflowError:
|
||||||
writeln(stdout, "the computation overflowed")
|
writeln(stdout, "the computation overflowed")
|
||||||
|
|
||||||
{.pop.} # overflow check
|
{.pop.} # overflow check
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
file: "toverflw2.nim"
|
file: "toverflw2.nim"
|
||||||
outputsub: "Error: unhandled exception: over- or underflow [EOverflow]"
|
outputsub: "Error: unhandled exception: over- or underflow [OverflowError]"
|
||||||
exitcode: "1"
|
exitcode: "1"
|
||||||
"""
|
"""
|
||||||
var a : int32 = 2147483647
|
var a : int32 = 2147483647
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
proc doSomething(v: Int, x: proc(v:Int):Int): Int = return x(v)
|
proc doSomething(v: int, x: proc(v:int):int): int = return x(v)
|
||||||
proc doSomething(v: Int, x: proc(v:Int)) = x(v)
|
proc doSomething(v: int, x: proc(v:int)) = x(v)
|
||||||
|
|
||||||
|
|
||||||
echo doSomething(10, proc(v: Int): Int = return v div 2)
|
echo doSomething(10, proc(v: int): int = return v div 2)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
type
|
type
|
||||||
PSDL_semaphore = ptr TSDL_semaphore
|
PSDL_semaphore = ptr TSDL_semaphore
|
||||||
TSDL_semaphore {.final.} = object
|
TSDL_semaphore {.final.} = object
|
||||||
sem: Pointer #PSem_t;
|
sem: pointer #PSem_t;
|
||||||
when not defined(USE_NAMED_SEMAPHORES):
|
when not defined(USE_NAMED_SEMAPHORES):
|
||||||
sem_data: int
|
sem_data: int
|
||||||
when defined(BROKEN_SEMGETVALUE):
|
when defined(BROKEN_SEMGETVALUE):
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,6 @@ type
|
||||||
kids: seq[TLegal]
|
kids: seq[TLegal]
|
||||||
|
|
||||||
TIllegal {.final.} = object #ERROR_MSG illegal recursion in type 'TIllegal'
|
TIllegal {.final.} = object #ERROR_MSG illegal recursion in type 'TIllegal'
|
||||||
y: Int
|
y: int
|
||||||
x: array[0..3, TIllegal]
|
x: array[0..3, TIllegal]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ proc main =
|
||||||
elif name == "name":
|
elif name == "name":
|
||||||
echo("Very funny, your name is name.")
|
echo("Very funny, your name is name.")
|
||||||
else:
|
else:
|
||||||
Echo("Hi, ", name, "!")
|
echo("Hi, ", name, "!")
|
||||||
|
|
||||||
let (x, y) = ("abc", name)
|
let (x, y) = ("abc", name)
|
||||||
echo y, x
|
echo y, x
|
||||||
|
|
|
||||||
|
|
@ -27,5 +27,5 @@ Possible Commands:
|
||||||
""" % [NimVersion & repeatChar(44-len(NimVersion)),
|
""" % [NimVersion & repeatChar(44-len(NimVersion)),
|
||||||
CompileDate, CompileTime]
|
CompileDate, CompileTime]
|
||||||
|
|
||||||
echo helpText
|
echo HelpText
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue