make at least bootstrapping work

This commit is contained in:
Araq 2018-08-05 14:17:24 +02:00
commit 7ac6462cbd
25 changed files with 1314 additions and 425 deletions

View file

@ -382,16 +382,24 @@ type
{.deprecated: [TBindSymRule: BindSymRule].}
proc bindSym*(ident: static[string], rule: BindSymRule = brClosed): NimNode {.
proc bindSym*(ident: string | NimNode, rule: BindSymRule = brClosed): NimNode {.
magic: "NBindSym", noSideEffect.}
## creates a node that binds `ident` to a symbol node. The bound symbol
## may be an overloaded symbol.
## if `ident` is a NimNode, it must have nkIdent kind.
## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is
## returned or ``nkSym`` if the symbol is not ambiguous.
## If ``rule == brOpen`` either an ``nkOpenSymChoice`` tree is
## returned or ``nkSym`` if the symbol is not ambiguous.
## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
## returned even if the symbol is not ambiguous.
##
## experimental feature:
## use {.experimental: "dynamicBindSym".} to activate it
## if called from template / regular code, `ident` and `rule` must be
## constant expression / literal value.
## if called from macros / compile time procs / static blocks,
## `ident` and `rule` can be VM computed value.
proc genSym*(kind: NimSymKind = nskLet; ident = ""): NimNode {.
magic: "NGenSym", noSideEffect.}
@ -425,6 +433,7 @@ proc getColumn(arg: NimNode): int {.magic: "NLineInfo", noSideEffect.}
proc getFile(arg: NimNode): string {.magic: "NLineInfo", noSideEffect.}
proc lineInfoObj*(n: NimNode): LineInfo {.compileTime.} =
## returns ``LineInfo`` of ``n``, using absolute path for ``filename``
result.filename = n.getFile
result.line = n.getLine
result.column = n.getColumn
@ -1284,7 +1293,7 @@ proc customPragmaNode(n: NimNode): NimNode =
let
typ = n.getTypeInst()
if typ.kind == nnkBracketExpr and typ.len > 1 and typ[1].kind == nnkProcTy:
if typ.kind == nnkBracketExpr and typ.len > 1 and typ[1].kind == nnkProcTy:
return typ[1][1]
elif typ.typeKind == ntyTypeDesc:
let impl = typ[1].getImpl()
@ -1319,6 +1328,8 @@ proc customPragmaNode(n: NimNode): NimNode =
if identDefs.kind == nnkRecCase:
identDefsStack.add(identDefs[0])
for i in 1..<identDefs.len:
# if it is and empty branch, skip
if identDefs[i][0].kind == nnkNilLit: continue
if identDefs[i][1].kind == nnkIdentDefs:
identDefsStack.add(identDefs[i][1])
else: # nnkRecList

View file

@ -449,10 +449,11 @@ proc generateSymbolIndex(symbols: seq[IndexEntry]): string =
desc = if not symbols[j].linkDesc.isNil: symbols[j].linkDesc else: ""
if desc.len > 0:
result.addf("""<li><a class="reference external"
title="$3" href="$1">$2</a></li>
title="$3" data-doc-search-tag="$2" href="$1">$2</a></li>
""", [url, text, desc])
else:
result.addf("""<li><a class="reference external" href="$1">$2</a></li>
result.addf("""<li><a class="reference external"
data-doc-search-tag="$2" href="$1">$2</a></li>
""", [url, text])
inc j
result.add("</ul></dd>\n")
@ -493,6 +494,7 @@ proc generateDocumentationTOC(entries: seq[IndexEntry]): string =
# Build a list of levels and extracted titles to make processing easier.
var
titleRef: string
titleTag: string
levels: seq[tuple[level: int, text: string]]
L = 0
level = 1
@ -519,10 +521,12 @@ proc generateDocumentationTOC(entries: seq[IndexEntry]): string =
let link = entries[L].link
if link.isDocumentationTitle:
titleRef = link
titleTag = levels[L].text
else:
result.add(level.indentToLevel(levels[L].level))
result.add("<li><a href=\"" & link & "\">" &
levels[L].text & "</a></li>\n")
result.addf("""<li><a class="reference" data-doc-search-tag="$1" href="$2">
$3</a></li>
""", [titleTag & " : " & levels[L].text, link, levels[L].text])
inc L
result.add(level.indentToLevel(1) & "</ul>\n")
assert(not titleRef.isNil,

View file

@ -854,20 +854,20 @@ when isMainModule:
doAssert numbers.distribute(6)[0] == @[1, 2]
doAssert numbers.distribute(6)[5] == @[7]
let a = @[1, 2, 3, 4, 5, 6, 7]
doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]]
doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]]
doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]]
doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]]
doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]]
doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]]
doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]]
doAssert a.distribute(6, false) == @[
doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]]
doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]]
doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]]
doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]]
doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]]
doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]]
doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]]
doAssert a.distribute(6, false) == @[
@[1, 2], @[3, 4], @[5, 6], @[7], @[], @[]]
doAssert a.distribute(8, false) == a.distribute(8, true)
doAssert a.distribute(8, false) == a.distribute(8, true)
doAssert a.distribute(90, false) == a.distribute(90, true)
var b = @[0]
for f in 1 .. 25: b.add(f)

View file

@ -347,6 +347,18 @@ proc excl*[A](s: var HashSet[A], other: HashSet[A]) =
assert other.isValid, "The set `other` needs to be initialized."
for item in other: discard exclImpl(s, item)
proc pop*[A](s: var HashSet[A]): A =
## Remove and return an arbitrary element from the set `s`.
##
## Raises KeyError if the set `s` is empty.
##
for h in 0..high(s.data):
if isFilled(s.data[h].hcode):
result = s.data[h].key
excl(s, result)
return result
raise newException(KeyError, "set is empty")
proc containsOrIncl*[A](s: var HashSet[A], key: A): bool =
## Includes `key` in the set `s` and tells if `key` was added to `s`.
##

View file

@ -332,7 +332,7 @@ when defined(windows):
if s.len == 0: return ""
# educated guess of capacity:
var cap = s.len + s.len shr 2
result = newStringOfCap(cap*2)
result = newString(cap*2)
# convert to utf-16 LE
var m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32,
lpMultiByteStr = cstring(s),
@ -347,7 +347,7 @@ when defined(windows):
lpWideCharStr = nil,
cchWideChar = cint(0))
# and do the conversion properly:
result = newStringOfCap(cap*2)
result = newString(cap*2)
m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32,
lpMultiByteStr = cstring(s),
cbMultiByte = cint(s.len),
@ -364,7 +364,7 @@ when defined(windows):
if int(c.dest) == 1200: return
# otherwise the fun starts again:
cap = s.len + s.len shr 2
var res = newStringOfCap(cap)
var res = newString(cap)
m = wideCharToMultiByte(
codePage = c.dest,
dwFlags = 0'i32,
@ -382,7 +382,7 @@ when defined(windows):
lpMultiByteStr = nil,
cbMultiByte = cint(0))
# and do the conversion properly:
res = newStringOfCap(cap)
res = newString(cap)
m = wideCharToMultiByte(
codePage = c.dest,
dwFlags = 0'i32,

View file

@ -60,7 +60,7 @@ proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} =
if additionalInfo.len == 0:
e.msg = osErrorMsg(errorCode)
else:
e.msg = osErrorMsg(errorCode) & "\nAdditional info: " & additionalInfo
e.msg = osErrorMsg(errorCode) & "\nAdditional info: '" & additionalInfo & "'"
if e.msg == "":
e.msg = "unknown OS error"
raise e

View file

@ -92,6 +92,9 @@ proc newSelector*[T](): Selector[T] =
result.maxFD = maxFD
result.fds = newSeq[SelectorKey[T]](maxFD)
for i in 0 ..< maxFD:
result.fds[i].ident = InvalidIdent
proc close*[T](s: Selector[T]) =
let res = posix.close(s.epollFD)
when hasThreadSupport:
@ -100,12 +103,6 @@ proc close*[T](s: Selector[T]) =
if res != 0:
raiseIOSelectorsError(osLastError())
template clearKey[T](key: ptr SelectorKey[T]) =
var empty: T
key.ident = 0
key.events = {}
key.data = empty
proc newSelectEvent*(): SelectEvent =
let fdci = eventfd(0, 0)
if fdci == -1:
@ -135,7 +132,7 @@ proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
events: set[Event], data: T) =
let fdi = int(fd)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0, "Descriptor $# already registered" % $fdi)
doAssert(s.fds[fdi].ident == InvalidIdent, "Descriptor $# already registered" % $fdi)
s.setKey(fdi, events, 0, data)
if events != {}:
var epv = EpollEvent(events: EPOLLRDHUP)
@ -152,7 +149,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle, events: set[Event]
let fdi = int(fd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0,
doAssert(pkey.ident != InvalidIdent,
"Descriptor $# is not registered in the selector!" % $fdi)
doAssert(pkey.events * maskEvents == {})
if pkey.events != events:
@ -180,7 +177,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
let fdi = int(fd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0,
doAssert(pkey.ident != InvalidIdent,
"Descriptor $# is not registered in the selector!" % $fdi)
if pkey.events != {}:
when not defined(android):
@ -243,7 +240,7 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) =
let fdi = int(ev.efd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0, "Event is not registered in the queue!")
doAssert(pkey.ident != InvalidIdent, "Event is not registered in the queue!")
doAssert(Event.User in pkey.events)
var epv = EpollEvent()
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
@ -262,7 +259,7 @@ proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
setNonBlocking(fdi.cint)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
var events = {Event.Timer}
var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP)
@ -307,7 +304,7 @@ when not defined(android):
setNonBlocking(fdi.cint)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP)
epv.data.u64 = fdi.uint
@ -334,7 +331,7 @@ when not defined(android):
setNonBlocking(fdi.cint)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP)
epv.data.u64 = fdi.uint
@ -347,7 +344,7 @@ when not defined(android):
proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
let fdi = int(ev.efd)
doAssert(s.fds[fdi].ident == 0, "Event is already registered in the queue!")
doAssert(s.fds[fdi].ident == InvalidIdent, "Event is already registered in the queue!")
s.setKey(fdi, {Event.User}, 0, data)
var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP)
epv.data.u64 = ev.efd.uint
@ -381,7 +378,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
let fdi = int(resTable[i].data.u64)
let pevents = resTable[i].events
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0)
doAssert(pkey.ident != InvalidIdent)
var rkey = ReadyKey(fd: fdi, events: {})
if (pevents and EPOLLERR) != 0 or (pevents and EPOLLHUP) != 0:
@ -482,7 +479,7 @@ template isEmpty*[T](s: Selector[T]): bool =
(s.count == 0)
proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} =
return s.fds[fd.int].ident != 0
return s.fds[fd.int].ident != InvalidIdent
proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T =
let fdi = int(fd)

View file

@ -114,6 +114,9 @@ proc newSelector*[T](): Selector[T] =
result.fds = newSeq[SelectorKey[T]](maxFD)
result.changes = newSeqOfCap[KEvent](MAX_KQUEUE_EVENTS)
for i in 0 ..< maxFD:
result.fds[i].ident = InvalidIdent
result.sock = usock
result.kqFD = kqFD
result.maxFD = maxFD.int
@ -128,12 +131,6 @@ proc close*[T](s: Selector[T]) =
if res1 != 0 or res2 != 0:
raiseIOSelectorsError(osLastError())
template clearKey[T](key: ptr SelectorKey[T]) =
var empty: T
key.ident = 0
key.events = {}
key.data = empty
proc newSelectEvent*(): SelectEvent =
var fds: array[2, cint]
if posix.pipe(fds) != 0:
@ -221,7 +218,7 @@ proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
events: set[Event], data: T) =
let fdi = int(fd)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
s.setKey(fdi, events, 0, data)
if events != {}:
@ -242,7 +239,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle,
let fdi = int(fd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0,
doAssert(pkey.ident != InvalidIdent,
"Descriptor $# is not registered in the queue!" % $fdi)
doAssert(pkey.events * maskEvents == {})
@ -269,7 +266,7 @@ proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
data: T): int {.discardable.} =
let fdi = getUnique(s)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
let events = if oneshot: {Event.Timer, Event.Oneshot} else: {Event.Timer}
let flags: cushort = if oneshot: EV_ONESHOT or EV_ADD else: EV_ADD
@ -291,7 +288,7 @@ proc registerSignal*[T](s: Selector[T], signal: int,
data: T): int {.discardable.} =
let fdi = getUnique(s)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
s.setKey(fdi, {Event.Signal}, signal, data)
var nmask, omask: Sigset
@ -315,7 +312,7 @@ proc registerProcess*[T](s: Selector[T], pid: int,
data: T): int {.discardable.} =
let fdi = getUnique(s)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
var kflags: cushort = EV_ONESHOT or EV_ADD
setKey(s, fdi, {Event.Process, Event.Oneshot}, pid, data)
@ -331,7 +328,7 @@ proc registerProcess*[T](s: Selector[T], pid: int,
proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
let fdi = ev.rfd.int
doAssert(s.fds[fdi].ident == 0, "Event is already registered in the queue!")
doAssert(s.fds[fdi].ident == InvalidIdent, "Event is already registered in the queue!")
setKey(s, fdi, {Event.User}, 0, data)
modifyKQueue(s, fdi.uint, EVFILT_READ, EV_ADD, 0, 0, nil)
@ -374,7 +371,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
let fdi = int(fd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0,
doAssert(pkey.ident != InvalidIdent,
"Descriptor [" & $fdi & "] is not registered in the queue!")
if pkey.events != {}:
@ -434,7 +431,7 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) =
let fdi = int(ev.rfd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0, "Event is not registered in the queue!")
doAssert(pkey.ident != InvalidIdent, "Event is not registered in the queue!")
doAssert(Event.User in pkey.events)
modifyKQueue(s, uint(fdi), EVFILT_READ, EV_DELETE, 0, 0, nil)
when not declared(CACHE_EVENTS):
@ -593,7 +590,7 @@ template isEmpty*[T](s: Selector[T]): bool =
(s.count == 0)
proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} =
return s.fds[fd.int].ident != 0
return s.fds[fd.int].ident != InvalidIdent
proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T =
let fdi = int(fd)

View file

@ -70,6 +70,9 @@ proc newSelector*[T](): Selector[T] =
result.fds = newSeq[SelectorKey[T]](maxFD)
result.pollfds = newSeq[TPollFd](maxFD)
for i in 0 ..< maxFD:
result.fds[i].ident = InvalidIdent
proc close*[T](s: Selector[T]) =
when hasThreadSupport:
deinitLock(s.lock)
@ -77,12 +80,6 @@ proc close*[T](s: Selector[T]) =
deallocSharedArray(s.pollfds)
deallocShared(cast[pointer](s))
template clearKey[T](key: ptr SelectorKey[T]) =
var empty: T
key.ident = 0
key.events = {}
key.data = empty
template pollAdd[T](s: Selector[T], sock: cint, events: set[Event]) =
withPollLock(s):
var pollev: cshort = 0
@ -135,7 +132,7 @@ proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
events: set[Event], data: T) =
var fdi = int(fd)
s.checkFd(fdi)
doAssert(s.fds[fdi].ident == 0)
doAssert(s.fds[fdi].ident == InvalidIdent)
setKey(s, fdi, events, 0, data)
if events != {}: s.pollAdd(fdi.cint, events)
@ -146,7 +143,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle,
let fdi = int(fd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0,
doAssert(pkey.ident != InvalidIdent,
"Descriptor [" & $fdi & "] is not registered in the queue!")
doAssert(pkey.events * maskEvents == {})
@ -162,7 +159,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle,
proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
var fdi = int(ev.rfd)
doAssert(s.fds[fdi].ident == 0, "Event is already registered in the queue!")
doAssert(s.fds[fdi].ident == InvalidIdent, "Event is already registered in the queue!")
var events = {Event.User}
setKey(s, fdi, events, 0, data)
events.incl(Event.Read)
@ -172,9 +169,9 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
let fdi = int(fd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0,
doAssert(pkey.ident != InvalidIdent,
"Descriptor [" & $fdi & "] is not registered in the queue!")
pkey.ident = 0
pkey.ident = InvalidIdent
pkey.events = {}
s.pollRemove(fdi.cint)
@ -182,9 +179,9 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) =
let fdi = int(ev.rfd)
s.checkFd(fdi)
var pkey = addr(s.fds[fdi])
doAssert(pkey.ident != 0, "Event is not registered in the queue!")
doAssert(pkey.ident != InvalidIdent, "Event is not registered in the queue!")
doAssert(Event.User in pkey.events)
pkey.ident = 0
pkey.ident = InvalidIdent
pkey.events = {}
s.pollRemove(fdi.cint)
@ -270,7 +267,7 @@ template isEmpty*[T](s: Selector[T]): bool =
(s.count == 0)
proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} =
return s.fds[fd.int].ident != 0
return s.fds[fd.int].ident != InvalidIdent
proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T =
let fdi = int(fd)

View file

@ -99,6 +99,9 @@ proc newSelector*[T](): Selector[T] =
result = Selector[T]()
result.fds = newSeq[SelectorKey[T]](FD_SETSIZE)
for i in 0 ..< FD_SETSIZE:
result.fds[i].ident = InvalidIdent
IOFD_ZERO(addr result.rSet)
IOFD_ZERO(addr result.wSet)
IOFD_ZERO(addr result.eSet)
@ -195,7 +198,7 @@ proc setSelectKey[T](s: Selector[T], fd: SocketHandle, events: set[Event],
var i = 0
let fdi = int(fd)
while i < FD_SETSIZE:
if s.fds[i].ident == 0:
if s.fds[i].ident == InvalidIdent:
var pkey = addr(s.fds[i])
pkey.ident = fdi
pkey.events = events
@ -221,7 +224,7 @@ proc delKey[T](s: Selector[T], fd: SocketHandle) =
var i = 0
while i < FD_SETSIZE:
if s.fds[i].ident == fd.int:
s.fds[i].ident = 0
s.fds[i].ident = InvalidIdent
s.fds[i].events = {}
s.fds[i].data = empty
break
@ -335,7 +338,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
var k = 0
while (i < FD_SETSIZE) and (k < count):
if s.fds[i].ident != 0:
if s.fds[i].ident != InvalidIdent:
var flag = false
var pkey = addr(s.fds[i])
var rkey = ReadyKey(fd: int(pkey.ident), events: {})

View file

@ -1004,6 +1004,13 @@ proc processElseBranch(recCaseNode, elseBranch, jsonNode, kindType,
exprColonExpr.add(ifStmt)
proc createConstructor(typeSym, jsonNode: NimNode): NimNode {.compileTime.}
proc detectDistinctType(typeSym: NimNode): NimNode =
let
typeImpl = getTypeImpl(typeSym)
typeInst = getTypeInst(typeSym)
result = if typeImpl.typeKind == ntyDistinct: typeImpl else: typeInst
proc processObjField(field, jsonNode: NimNode): seq[NimNode] =
## Process a field from a ``RecList``.
##
@ -1022,8 +1029,8 @@ proc processObjField(field, jsonNode: NimNode): seq[NimNode] =
# Add the field value.
# -> jsonNode["`field`"]
let indexedJsonNode = createJsonIndexer(jsonNode, $field)
exprColonExpr.add(createConstructor(getTypeInst(field), indexedJsonNode))
let typeNode = detectDistinctType(field)
exprColonExpr.add(createConstructor(typeNode, indexedJsonNode))
of nnkRecCase:
# A "case" field that introduces a variant.
let exprColonExpr = newNimNode(nnkExprColonExpr)
@ -1248,7 +1255,7 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
let seqT = typeSym[1]
let forLoopI = genSym(nskForVar, "i")
let indexerNode = createJsonIndexer(jsonNode, forLoopI)
let constructorNode = createConstructor(seqT, indexerNode)
let constructorNode = createConstructor(detectDistinctType(seqT), indexerNode)
# Create a statement expression containing a for loop.
result = quote do:
@ -1284,7 +1291,10 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
# Handle all other types.
let obj = getType(typeSym)
if obj.kind == nnkBracketExpr:
let typeNode = getTypeImpl(typeSym)
if typeNode.typeKind == ntyDistinct:
result = createConstructor(typeNode, jsonNode)
elif obj.kind == nnkBracketExpr:
# When `Sym "Foo"` turns out to be a `ref object`.
result = createConstructor(obj, jsonNode)
else:
@ -1295,6 +1305,21 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
# TODO: The fact that `jsonNode` here works to give a good line number
# is weird. Specifying typeSym should work but doesn't.
error("Use a named tuple instead of: " & $toStrLit(typeSym), jsonNode)
of nnkDistinctTy:
var baseType = typeSym
# solve nested distinct types
while baseType.typeKind == ntyDistinct:
let impl = getTypeImpl(baseType[0])
if impl.typeKind != ntyDistinct:
baseType = baseType[0]
break
baseType = impl
let ret = createConstructor(baseType, jsonNode)
let typeInst = getTypeInst(typeSym)
result = quote do:
(
`typeInst`(`ret`)
)
else:
doAssert false, "Unable to create constructor for: " & $typeSym.kind
@ -1418,7 +1443,7 @@ macro to*(node: JsonNode, T: typedesc): untyped =
## doAssert data.person.age == 21
## doAssert data.list == @[1, 2, 3, 4]
let typeNode = getTypeInst(T)
let typeNode = getTypeImpl(T)
expectKind(typeNode, nnkBracketExpr)
doAssert(($typeNode[0]).normalize == "typedesc")

View file

@ -231,6 +231,7 @@ const mimes* = {
"xcf": "application/x-xcf",
"fig": "application/x-xfig",
"xpi": "application/x-xpinstall",
"wasm": "application/wasm",
"amr": "audio/amr",
"awb": "audio/amr-wb",
"amr": "audio/amr",

View file

@ -41,7 +41,7 @@
## immediately.
##
## .. code-block:: Nim
## var socket = newSocket()
## var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
## socket.sendTo("192.168.0.1", Port(27960), "status\n")
##
## Creating a server

View file

@ -971,7 +971,7 @@ proc rawCreateDir(dir: string): bool =
elif errno in {EEXIST, ENOSYS}:
result = false
else:
raiseOSError(osLastError())
raiseOSError(osLastError(), dir)
elif defined(posix):
let res = mkdir(dir, 0o777)
if res == 0'i32:
@ -980,7 +980,7 @@ proc rawCreateDir(dir: string): bool =
result = false
else:
#echo res
raiseOSError(osLastError())
raiseOSError(osLastError(), dir)
else:
when useWinUnicode:
wrapUnary(res, createDirectoryW, dir)
@ -992,7 +992,7 @@ proc rawCreateDir(dir: string): bool =
elif getLastError() == 183'i32:
result = false
else:
raiseOSError(osLastError())
raiseOSError(osLastError(), dir)
proc existsOrCreateDir*(dir: string): bool {.rtl, extern: "nos$1",
tags: [WriteDirEffect, ReadDirEffect].} =
@ -1005,7 +1005,7 @@ proc existsOrCreateDir*(dir: string): bool {.rtl, extern: "nos$1",
if result:
# path already exists - need to check that it is indeed a directory
if not existsDir(dir):
raise newException(IOError, "Failed to create the directory")
raise newException(IOError, "Failed to create '" & dir & "'")
proc createDir*(dir: string) {.rtl, extern: "nos$1",
tags: [WriteDirEffect, ReadDirEffect].} =

View file

@ -147,7 +147,7 @@ else: # UNIX-like operating system
DirSep* = '/'
AltSep* = DirSep
PathSep* = ':'
FileSystemCaseSensitive* = true
FileSystemCaseSensitive* = when defined(macosx): false else: true
ExeExt* = ""
ScriptExt* = ""
DynlibFormat* = when defined(macosx): "lib$1.dylib" else: "lib$1.so"
@ -410,6 +410,11 @@ proc cmpPaths*(pathA, pathB: string): int {.
## | 0 iff pathA == pathB
## | < 0 iff pathA < pathB
## | > 0 iff pathA > pathB
runnableExamples:
when defined(macosx):
doAssert cmpPaths("foo", "Foo") == 0
elif defined(posix):
doAssert cmpPaths("foo", "Foo") > 0
if FileSystemCaseSensitive:
result = cmp(pathA, pathB)
else:

View file

@ -110,7 +110,7 @@ proc random*[T](a: openArray[T]): T {.deprecated.} =
## Use ``rand`` instead.
result = a[random(a.low..a.len)]
proc rand*(r: var Rand; max: int): int {.benign.} =
proc rand*(r: var Rand; max: Natural): int {.benign.} =
## Returns a random number in the range 0..max. The sequence of
## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random"
@ -128,7 +128,7 @@ proc rand*(max: int): int {.benign.} =
## number, i.e. a tickcount.
rand(state, max)
proc rand*(r: var Rand; max: float): float {.benign.} =
proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} =
## Returns a random number in the range 0..max. The sequence of
## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random"
@ -218,4 +218,17 @@ when isMainModule:
doAssert rand(0) == 0
doAssert rand("a") == 'a'
when compileOption("rangeChecks"):
try:
discard rand(-1)
doAssert false
except RangeError:
discard
try:
discard rand(-1.0)
doAssert false
except RangeError:
discard
main()

View file

@ -261,6 +261,9 @@ else:
param: int
data: T
const
InvalidIdent = -1
proc raiseIOSelectorsError[T](message: T) =
var msg = ""
when T is string:
@ -302,6 +305,12 @@ else:
if posix.sigprocmask(SIG_UNBLOCK, newmask, oldmask) == -1:
raiseIOSelectorsError(osLastError())
template clearKey[T](key: ptr SelectorKey[T]) =
var empty: T
key.ident = InvalidIdent
key.events = {}
key.data = empty
when defined(linux):
include ioselects/ioselectors_epoll
elif bsdPlatform:

View file

@ -181,10 +181,27 @@ elif defined(windows):
type
Month* = enum ## Represents a month. Note that the enum starts at ``1``, so ``ord(month)`` will give
## the month number in the range ``[1..12]``.
mJan = 1, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
mJan = (1, "January")
mFeb = "February"
mMar = "March"
mApr = "April"
mMay = "May"
mJun = "June"
mJul = "July"
mAug = "August"
mSep = "September"
mOct = "October"
mNov = "November"
mDec = "December"
WeekDay* = enum ## Represents a weekday.
dMon, dTue, dWed, dThu, dFri, dSat, dSun
dMon = "Monday"
dTue = "Tuesday"
dWed = "Wednesday"
dThu = "Thursday"
dFri = "Friday"
dSat = "Saturday"
dSun = "Sunday"
MonthdayRange* = range[1..31]
HourRange* = range[0..23]
@ -1074,20 +1091,6 @@ proc getClockStr*(): string {.rtl, extern: "nt$1", tags: [TimeEffect].} =
result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) &
':' & intToStr(ti.second, 2)
proc `$`*(day: WeekDay): string =
## Stringify operator for ``WeekDay``.
const lookup: array[WeekDay, string] = ["Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday"]
return lookup[day]
proc `$`*(m: Month): string =
## Stringify operator for ``Month``.
const lookup: array[Month, string] = ["January", "February", "March",
"April", "May", "June", "July", "August", "September", "October",
"November", "December"]
return lookup[m]
proc toParts* (ti: TimeInterval): TimeIntervalParts =
## Converts a `TimeInterval` into an array consisting of its time units,
## starting with nanoseconds and ending with years

View file

@ -1479,8 +1479,8 @@ when defined(nimdoc):
##
## Note that this is a *runtime* call and using ``quit`` inside a macro won't
## have any compile time effect. If you need to stop the compiler inside a
## macro, use the `error <manual.html#error-pragma>`_ or `fatal
## <manual.html#fatal-pragma>`_ pragmas.
## macro, use the `error <manual.html#pragmas-error-pragma>`_ or `fatal
## <manual.html#pragmas-fatal-pragma>`_ pragmas.
elif defined(genode):
include genode/env
@ -2438,7 +2438,7 @@ iterator fieldPairs*[T: tuple|object](x: T): RootObj {.
## When you iterate over objects with different field types you have to use
## the compile time ``when`` instead of a runtime ``if`` to select the code
## you want to run for each type. To perform the comparison use the `is
## operator <manual.html#is-operator>`_. Example:
## operator <manual.html#generics-is-operator>`_. Example:
##
## .. code-block:: Nim
##
@ -3788,7 +3788,9 @@ template doAssert*(cond: bool, msg = "") =
## same as `assert` but is always turned on and not affected by the
## ``--assertions`` command line switch.
bind instantiationInfo
{.line: instantiationInfo().}:
# NOTE: `true` is correct here; --excessiveStackTrace:on will control whether
# or not to output full paths.
{.line: instantiationInfo(-1, true).}:
if not cond:
raiseAssert(astToStr(cond) & ' ' &
instantiationInfo(-1, false).fileName & '(' &

View file

@ -116,6 +116,8 @@ type
nextChunkSize: int
bottomData: AvlNode
heapLinks: HeapLinks
when defined(nimTypeNames):
allocCounter, deallocCounter: int
const
fsLookupTable: array[byte, int8] = [
@ -434,8 +436,9 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
a.nextChunkSize = PageSize*4
else:
a.nextChunkSize = min(roundup(usedMem shr 2, PageSize), a.nextChunkSize * 2)
var size = size
a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize)
var size = size
if size > a.nextChunkSize:
result = cast[PBigChunk](osAllocPages(size))
else:
@ -737,6 +740,8 @@ when false:
result = nil
proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
when defined(nimTypeNames):
inc(a.allocCounter)
sysAssert(allocInv(a), "rawAlloc: begin")
sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
sysAssert(requestedSize >= sizeof(FreeCell), "rawAlloc: requested size too small")
@ -810,6 +815,8 @@ proc rawAlloc0(a: var MemRegion, requestedSize: int): pointer =
zeroMem(result, requestedSize)
proc rawDealloc(a: var MemRegion, p: pointer) =
when defined(nimTypeNames):
inc(a.deallocCounter)
#sysAssert(isAllocatedPtr(a, p), "rawDealloc: no allocated pointer")
sysAssert(allocInv(a), "rawDealloc: begin")
var c = pageAddr(p)
@ -975,6 +982,10 @@ proc getOccupiedMem(a: MemRegion): int {.inline.} =
result = a.occ
# a.currMem - a.freeMem
when defined(nimTypeNames):
proc getMemCounters(a: MemRegion): (int, int) {.inline.} =
(a.allocCounter, a.deallocCounter)
# ---------------------- thread memory region -------------------------------
template instantiateForRegion(allocator: untyped) =
@ -1018,6 +1029,9 @@ template instantiateForRegion(allocator: untyped) =
proc getOccupiedMem(): int = return allocator.occ #getTotalMem() - getFreeMem()
proc getMaxMem*(): int = return getMaxMem(allocator)
when defined(nimTypeNames):
proc getMemCounters*(): (int, int) = getMemCounters(allocator)
# -------------------- shared heap region ----------------------------------
when hasThreadSupport:
var sharedHeap: MemRegion

Some files were not shown because too many files have changed in this diff Show more