fixex merge conflicts
This commit is contained in:
commit
8e9551b1c7
53 changed files with 2648 additions and 355 deletions
|
|
@ -10,11 +10,11 @@
|
|||
## Regular expression support for Nim.
|
||||
##
|
||||
## This module is implemented by providing a wrapper around the
|
||||
## `PRCE (Perl-Compatible Regular Expressions) <http://www.pcre.org>`_
|
||||
## C library. This means that your application will depend on the PRCE
|
||||
## `PCRE (Perl-Compatible Regular Expressions) <http://www.pcre.org>`_
|
||||
## C library. This means that your application will depend on the PCRE
|
||||
## library's licence when using this module, which should not be a problem
|
||||
## though.
|
||||
## PRCE's licence follows:
|
||||
## PCRE's licence follows:
|
||||
##
|
||||
## .. include:: ../../doc/regexprs.txt
|
||||
##
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ proc nimNumber(g: var GeneralTokenizer, position: int): int =
|
|||
|
||||
const
|
||||
OpChars = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.',
|
||||
'|', '=', '%', '&', '$', '@', '~', ':', '\x80'..'\xFF'}
|
||||
'|', '=', '%', '&', '$', '@', '~', ':'}
|
||||
|
||||
proc nimNextToken(g: var GeneralTokenizer) =
|
||||
const
|
||||
|
|
|
|||
|
|
@ -82,6 +82,14 @@ const
|
|||
# Special types
|
||||
type Sighandler = proc (a: cint) {.noconv.}
|
||||
|
||||
const StatHasNanoseconds* = defined(linux) or defined(freebsd) or
|
||||
defined(openbsd) or defined(dragonfly) ## \
|
||||
## Boolean flag that indicates if the system supports nanosecond time
|
||||
## resolution in the fields of ``Stat``. Note that the nanosecond based fields
|
||||
## (``Stat.st_atim``, ``Stat.st_mtim`` and ``Stat.st_ctim``) can be accessed
|
||||
## without checking this flag, because this module defines fallback procs
|
||||
## when they are not available.
|
||||
|
||||
# Platform specific stuff
|
||||
|
||||
when defined(linux) and defined(amd64):
|
||||
|
|
@ -92,9 +100,9 @@ else:
|
|||
# There used to be this name in posix.nim a long time ago, not sure why!
|
||||
{.deprecated: [cSIG_HOLD: SIG_HOLD].}
|
||||
|
||||
when not defined(macosx) and not defined(android):
|
||||
when StatHasNanoseconds:
|
||||
proc st_atime*(s: Stat): Time {.inline.} =
|
||||
## Second-granularity time of last access
|
||||
## Second-granularity time of last access.
|
||||
result = s.st_atim.tv_sec
|
||||
proc st_mtime*(s: Stat): Time {.inline.} =
|
||||
## Second-granularity time of last data modification.
|
||||
|
|
@ -102,6 +110,16 @@ when not defined(macosx) and not defined(android):
|
|||
proc st_ctime*(s: Stat): Time {.inline.} =
|
||||
## Second-granularity time of last status change.
|
||||
result = s.st_ctim.tv_sec
|
||||
else:
|
||||
proc st_atim*(s: Stat): TimeSpec {.inline.} =
|
||||
## Nanosecond-granularity time of last access.
|
||||
result.tv_sec = s.st_atime
|
||||
proc st_mtim*(s: Stat): TimeSpec {.inline.} =
|
||||
## Nanosecond-granularity time of last data modification.
|
||||
result.tv_sec = s.st_mtime
|
||||
proc st_ctim*(s: Stat): TimeSpec {.inline.} =
|
||||
## Nanosecond-granularity time of last data modification.
|
||||
result.tv_sec = s.st_ctime
|
||||
|
||||
when hasAioH:
|
||||
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
|
|
|
|||
|
|
@ -215,14 +215,14 @@ type
|
|||
## For a typed memory object, the length in bytes.
|
||||
## For other file types, the use of this field is
|
||||
## unspecified.
|
||||
when defined(macosx) or defined(android):
|
||||
st_atime*: Time ## Time of last access.
|
||||
st_mtime*: Time ## Time of last data modification.
|
||||
st_ctime*: Time ## Time of last status change.
|
||||
else:
|
||||
when StatHasNanoseconds:
|
||||
st_atim*: Timespec ## Time of last access.
|
||||
st_mtim*: Timespec ## Time of last data modification.
|
||||
st_ctim*: Timespec ## Time of last status change.
|
||||
else:
|
||||
st_atime*: Time ## Time of last access.
|
||||
st_mtime*: Time ## Time of last data modification.
|
||||
st_ctime*: Time ## Time of last status change.
|
||||
st_blksize*: Blksize ## A file system-specific preferred I/O block size
|
||||
## for this object. In some file system types, this
|
||||
## may vary from file to file.
|
||||
|
|
|
|||
|
|
@ -62,52 +62,6 @@ template createCb(retFutureSym, iteratorNameSym,
|
|||
|
||||
identName()
|
||||
#{.pop.}
|
||||
proc generateExceptionCheck(futSym,
|
||||
tryStmt, rootReceiver, fromNode: NimNode): NimNode {.compileTime.} =
|
||||
if tryStmt.kind == nnkNilLit:
|
||||
result = rootReceiver
|
||||
else:
|
||||
var exceptionChecks: seq[tuple[cond, body: NimNode]] = @[]
|
||||
let errorNode = newDotExpr(futSym, newIdentNode("error"))
|
||||
for i in 1 ..< tryStmt.len:
|
||||
let exceptBranch = tryStmt[i]
|
||||
if exceptBranch[0].kind == nnkStmtList:
|
||||
exceptionChecks.add((newIdentNode("true"), exceptBranch[0]))
|
||||
else:
|
||||
var exceptIdentCount = 0
|
||||
var ifCond: NimNode
|
||||
for i in 0 ..< exceptBranch.len:
|
||||
let child = exceptBranch[i]
|
||||
if child.kind == nnkIdent:
|
||||
let cond = infix(errorNode, "of", child)
|
||||
if exceptIdentCount == 0:
|
||||
ifCond = cond
|
||||
else:
|
||||
ifCond = infix(ifCond, "or", cond)
|
||||
else:
|
||||
break
|
||||
exceptIdentCount.inc
|
||||
|
||||
expectKind(exceptBranch[exceptIdentCount], nnkStmtList)
|
||||
exceptionChecks.add((ifCond, exceptBranch[exceptIdentCount]))
|
||||
# -> -> else: raise futSym.error
|
||||
exceptionChecks.add((newIdentNode("true"),
|
||||
newNimNode(nnkRaiseStmt).add(errorNode)))
|
||||
# Read the future if there is no error.
|
||||
# -> else: futSym.read
|
||||
let elseNode = newNimNode(nnkElse, fromNode)
|
||||
elseNode.add newNimNode(nnkStmtList, fromNode)
|
||||
elseNode[0].add rootReceiver
|
||||
|
||||
let ifBody = newStmtList()
|
||||
ifBody.add newCall(newIdentNode("setCurrentException"), errorNode)
|
||||
ifBody.add newIfStmt(exceptionChecks)
|
||||
ifBody.add newCall(newIdentNode("setCurrentException"), newNilLit())
|
||||
|
||||
result = newIfStmt(
|
||||
(newDotExpr(futSym, newIdentNode("failed")), ifBody)
|
||||
)
|
||||
result.add elseNode
|
||||
|
||||
template useVar(result: var NimNode, futureVarNode: NimNode, valueReceiver,
|
||||
rootReceiver: untyped, fromNode: NimNode) =
|
||||
|
|
@ -123,8 +77,7 @@ template useVar(result: var NimNode, futureVarNode: NimNode, valueReceiver,
|
|||
result.add newNimNode(nnkYieldStmt, fromNode).add(futureVarNode)
|
||||
# -> future<x>.read
|
||||
valueReceiver = newDotExpr(futureVarNode, newIdentNode("read"))
|
||||
result.add generateExceptionCheck(futureVarNode, tryStmt, rootReceiver,
|
||||
fromNode)
|
||||
result.add rootReceiver
|
||||
|
||||
template createVar(result: var NimNode, futSymName: string,
|
||||
asyncProc: NimNode,
|
||||
|
|
@ -154,8 +107,8 @@ proc createFutureVarCompletions(futureVarIdents: seq[NimNode],
|
|||
)
|
||||
|
||||
proc processBody(node, retFutureSym: NimNode,
|
||||
subTypeIsVoid: bool, futureVarIdents: seq[NimNode],
|
||||
tryStmt: NimNode): NimNode {.compileTime.} =
|
||||
subTypeIsVoid: bool,
|
||||
futureVarIdents: seq[NimNode]): NimNode {.compileTime.} =
|
||||
#echo(node.treeRepr)
|
||||
result = node
|
||||
case node.kind
|
||||
|
|
@ -173,7 +126,7 @@ proc processBody(node, retFutureSym: NimNode,
|
|||
result.add newCall(newIdentNode("complete"), retFutureSym)
|
||||
else:
|
||||
let x = node[0].processBody(retFutureSym, subTypeIsVoid,
|
||||
futureVarIdents, tryStmt)
|
||||
futureVarIdents)
|
||||
if x.kind == nnkYieldStmt: result.add x
|
||||
else:
|
||||
result.add newCall(newIdentNode("complete"), retFutureSym, x)
|
||||
|
|
@ -224,63 +177,11 @@ proc processBody(node, retFutureSym: NimNode,
|
|||
var newDiscard = node
|
||||
result.createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1],
|
||||
newDiscard[0], newDiscard, node)
|
||||
of nnkTryStmt:
|
||||
# try: await x; except: ...
|
||||
result = newNimNode(nnkStmtList, node)
|
||||
template wrapInTry(n, tryBody: untyped) =
|
||||
var temp = n
|
||||
n[0] = tryBody
|
||||
tryBody = temp
|
||||
|
||||
# Transform ``except`` body.
|
||||
# TODO: Could we perform some ``await`` transformation here to get it
|
||||
# working in ``except``?
|
||||
tryBody[1] = processBody(n[1], retFutureSym, subTypeIsVoid,
|
||||
futureVarIdents, nil)
|
||||
|
||||
proc processForTry(n: NimNode, i: var int,
|
||||
res: NimNode): bool {.compileTime.} =
|
||||
## Transforms the body of the tryStmt. Does not transform the
|
||||
## body in ``except``.
|
||||
## Returns true if the tryStmt node was transformed into an ifStmt.
|
||||
result = false
|
||||
var skipped = n.skipStmtList()
|
||||
while i < skipped.len:
|
||||
var processed = processBody(skipped[i], retFutureSym,
|
||||
subTypeIsVoid, futureVarIdents, n)
|
||||
|
||||
# Check if we transformed the node into an exception check.
|
||||
# This suggests skipped[i] contains ``await``.
|
||||
if processed.kind != skipped[i].kind or processed.len != skipped[i].len:
|
||||
processed = processed.skipUntilStmtList()
|
||||
expectKind(processed, nnkStmtList)
|
||||
expectKind(processed[2][1], nnkElse)
|
||||
i.inc
|
||||
|
||||
if not processForTry(n, i, processed[2][1][0]):
|
||||
# We need to wrap the nnkElse nodes back into a tryStmt.
|
||||
# As they are executed if an exception does not happen
|
||||
# inside the awaited future.
|
||||
# The following code will wrap the nodes inside the
|
||||
# original tryStmt.
|
||||
wrapInTry(n, processed[2][1][0])
|
||||
|
||||
res.add processed
|
||||
result = true
|
||||
else:
|
||||
res.add skipped[i]
|
||||
i.inc
|
||||
var i = 0
|
||||
if not processForTry(node, i, result):
|
||||
# If the tryStmt hasn't been transformed we can just put the body
|
||||
# back into it.
|
||||
wrapInTry(node, result)
|
||||
return
|
||||
else: discard
|
||||
|
||||
for i in 0 ..< result.len:
|
||||
result[i] = processBody(result[i], retFutureSym, subTypeIsVoid,
|
||||
futureVarIdents, nil)
|
||||
futureVarIdents)
|
||||
|
||||
proc getName(node: NimNode): string {.compileTime.} =
|
||||
case node.kind
|
||||
|
|
@ -362,7 +263,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
|
|||
# -> complete(retFuture, result)
|
||||
var iteratorNameSym = genSym(nskIterator, $prcName & "Iter")
|
||||
var procBody = prc.body.processBody(retFutureSym, subtypeIsVoid,
|
||||
futureVarIdents, nil)
|
||||
futureVarIdents)
|
||||
# don't do anything with forward bodies (empty)
|
||||
if procBody.kind != nnkEmpty:
|
||||
procBody.add(createFutureVarCompletions(futureVarIdents, nil))
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ proc inc*(c: var CritBitTree[int]; key: string, val: int = 1) =
|
|||
## increments `c[key]` by `val`.
|
||||
let oldCount = c.count
|
||||
var n = rawInsert(c, key)
|
||||
if c.count == oldCount or oldCount == 0:
|
||||
if c.count >= oldCount or oldCount == 0:
|
||||
# not a new key:
|
||||
inc n.val, val
|
||||
|
||||
|
|
@ -322,10 +322,14 @@ proc `$`*[T](c: CritBitTree[T]): string =
|
|||
const avgItemLen = 16
|
||||
result = newStringOfCap(c.count * avgItemLen)
|
||||
result.add("{")
|
||||
for key, val in pairs(c):
|
||||
if result.len > 1: result.add(", ")
|
||||
result.add($key)
|
||||
when T isnot void:
|
||||
when T is void:
|
||||
for key in keys(c):
|
||||
if result.len > 1: result.add(", ")
|
||||
result.addQuoted(key)
|
||||
else:
|
||||
for key, val in pairs(c):
|
||||
if result.len > 1: result.add(", ")
|
||||
result.addQuoted(key)
|
||||
result.add(": ")
|
||||
result.addQuoted(val)
|
||||
result.add("}")
|
||||
|
|
@ -362,3 +366,12 @@ when isMainModule:
|
|||
|
||||
c.inc("a", -5)
|
||||
assert c["a"] == 0
|
||||
|
||||
c.inc("b", 2)
|
||||
assert c["b"] == 2
|
||||
|
||||
c.inc("c", 3)
|
||||
assert c["c"] == 3
|
||||
|
||||
c.inc("a", 1)
|
||||
assert c["a"] == 1
|
||||
|
|
|
|||
|
|
@ -328,14 +328,14 @@ proc toJson(x: NimNode): NimNode {.compiletime.} =
|
|||
result = newNimNode(nnkBracket)
|
||||
for i in 0 ..< x.len:
|
||||
result.add(toJson(x[i]))
|
||||
result = newCall(bindSym"%", result)
|
||||
result = newCall(bindSym("%", brOpen), result)
|
||||
of nnkTableConstr: # object
|
||||
if x.len == 0: return newCall(bindSym"newJObject")
|
||||
result = newNimNode(nnkTableConstr)
|
||||
for i in 0 ..< x.len:
|
||||
x[i].expectKind nnkExprColonExpr
|
||||
result.add newTree(nnkExprColonExpr, x[i][0], toJson(x[i][1]))
|
||||
result = newCall(bindSym"%", result)
|
||||
result = newCall(bindSym("%", brOpen), result)
|
||||
of nnkCurly: # empty object
|
||||
x.expectLen(0)
|
||||
result = newCall(bindSym"newJObject")
|
||||
|
|
@ -343,9 +343,9 @@ proc toJson(x: NimNode): NimNode {.compiletime.} =
|
|||
result = newCall(bindSym"newJNull")
|
||||
of nnkPar:
|
||||
if x.len == 1: result = toJson(x[0])
|
||||
else: result = newCall(bindSym"%", x)
|
||||
else: result = newCall(bindSym("%", brOpen), x)
|
||||
else:
|
||||
result = newCall(bindSym"%", x)
|
||||
result = newCall(bindSym("%", brOpen), x)
|
||||
|
||||
macro `%*`*(x: untyped): untyped =
|
||||
## Convert an expression to a JsonNode directly, without having to specify
|
||||
|
|
|
|||
|
|
@ -129,6 +129,12 @@ proc sum*[T](x: openArray[T]): T {.noSideEffect.} =
|
|||
## If `x` is empty, 0 is returned.
|
||||
for i in items(x): result = result + i
|
||||
|
||||
proc prod*[T](x: openArray[T]): T {.noSideEffect.} =
|
||||
## Computes the product of the elements in ``x``.
|
||||
## If ``x`` is empty, 1 is returned.
|
||||
result = 1.T
|
||||
for i in items(x): result = result * i
|
||||
|
||||
{.push noSideEffect.}
|
||||
when not defined(JS): # C
|
||||
proc sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".}
|
||||
|
|
@ -274,12 +280,18 @@ when not defined(JS): # C
|
|||
proc erfc*(x: float64): float64 {.importc: "erfc", header: "<math.h>".}
|
||||
## The complementary error function
|
||||
|
||||
proc gamma*(x: float32): float32 {.importc: "tgammaf", header: "<math.h>".}
|
||||
proc gamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".}
|
||||
## The gamma function
|
||||
proc tgamma*(x: float32): float32
|
||||
{.deprecated: "use gamma instead", importc: "tgammaf", header: "<math.h>".}
|
||||
proc tgamma*(x: float64): float64
|
||||
{.deprecated: "use gamma instead", importc: "tgamma", header: "<math.h>".}
|
||||
## The gamma function
|
||||
## **Deprecated since version 0.19.0**: Use ``gamma`` instead.
|
||||
proc lgamma*(x: float32): float32 {.importc: "lgammaf", header: "<math.h>".}
|
||||
proc lgamma*(x: float64): float64 {.importc: "lgamma", header: "<math.h>".}
|
||||
## Natural log of the gamma function
|
||||
proc tgamma*(x: float32): float32 {.importc: "tgammaf", header: "<math.h>".}
|
||||
proc tgamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".}
|
||||
## The gamma function
|
||||
|
||||
proc floor*(x: float32): float32 {.importc: "floorf", header: "<math.h>".}
|
||||
proc floor*(x: float64): float64 {.importc: "floor", header: "<math.h>".}
|
||||
|
|
@ -372,7 +384,7 @@ when not defined(JS): # C
|
|||
|
||||
proc `mod`*(x, y: float32): float32 {.importc: "fmodf", header: "<math.h>".}
|
||||
proc `mod`*(x, y: float64): float64 {.importc: "fmod", header: "<math.h>".}
|
||||
## Computes the modulo operation for float operators.
|
||||
## Computes the modulo operation for float operators.
|
||||
else: # JS
|
||||
proc hypot*[T: float32|float64](x, y: T): T = return sqrt(x*x + y*y)
|
||||
proc pow*(x, y: float32): float32 {.importC: "Math.pow", nodecl.}
|
||||
|
|
@ -551,6 +563,7 @@ when isMainModule and not defined(JS):
|
|||
return sqrt(num)
|
||||
|
||||
# check gamma function
|
||||
assert(gamma(5.0) == 24.0) # 4!
|
||||
assert($tgamma(5.0) == $24.0) # 4!
|
||||
assert(lgamma(1.0) == 0.0) # ln(1.0) == 0.0
|
||||
assert(erf(6.0) > erf(5.0))
|
||||
|
|
@ -560,6 +573,12 @@ when isMainModule:
|
|||
# Function for approximate comparison of floats
|
||||
proc `==~`(x, y: float): bool = (abs(x-y) < 1e-9)
|
||||
|
||||
block: # prod
|
||||
doAssert prod([1, 2, 3, 4]) == 24
|
||||
doAssert prod([1.5, 3.4]) == 5.1
|
||||
let x: seq[float] = @[]
|
||||
doAssert prod(x) == 1.0
|
||||
|
||||
block: # round() tests
|
||||
# Round to 0 decimal places
|
||||
doAssert round(54.652) ==~ 55.0
|
||||
|
|
|
|||
|
|
@ -405,33 +405,40 @@ proc isIpAddress*(address_str: string): bool {.tags: [].} =
|
|||
return false
|
||||
return true
|
||||
|
||||
proc toSockAddr*(address: IpAddress, port: Port, sa: var Sockaddr_storage, sl: var Socklen) =
|
||||
proc toSockAddr*(address: IpAddress, port: Port, sa: var Sockaddr_storage,
|
||||
sl: var Socklen) =
|
||||
## Converts `IpAddress` and `Port` to `SockAddr` and `Socklen`
|
||||
let port = htons(uint16(port))
|
||||
case address.family
|
||||
of IpAddressFamily.IPv4:
|
||||
sl = sizeof(Sockaddr_in).Socklen
|
||||
let s = cast[ptr Sockaddr_in](addr sa)
|
||||
s.sin_family = type(s.sin_family)(AF_INET)
|
||||
s.sin_family = type(s.sin_family)(toInt(AF_INET))
|
||||
s.sin_port = port
|
||||
copyMem(addr s.sin_addr, unsafeAddr address.address_v4[0], sizeof(s.sin_addr))
|
||||
copyMem(addr s.sin_addr, unsafeAddr address.address_v4[0],
|
||||
sizeof(s.sin_addr))
|
||||
of IpAddressFamily.IPv6:
|
||||
sl = sizeof(Sockaddr_in6).Socklen
|
||||
let s = cast[ptr Sockaddr_in6](addr sa)
|
||||
s.sin6_family = type(s.sin6_family)(AF_INET6)
|
||||
s.sin6_family = type(s.sin6_family)(toInt(AF_INET6))
|
||||
s.sin6_port = port
|
||||
copyMem(addr s.sin6_addr, unsafeAddr address.address_v6[0], sizeof(s.sin6_addr))
|
||||
copyMem(addr s.sin6_addr, unsafeAddr address.address_v6[0],
|
||||
sizeof(s.sin6_addr))
|
||||
|
||||
proc fromSockAddrAux(sa: ptr Sockaddr_storage, sl: Socklen, address: var IpAddress, port: var Port) =
|
||||
if sa.ss_family.int == AF_INET.int and sl == sizeof(Sockaddr_in).Socklen:
|
||||
proc fromSockAddrAux(sa: ptr Sockaddr_storage, sl: Socklen,
|
||||
address: var IpAddress, port: var Port) =
|
||||
if sa.ss_family.int == toInt(AF_INET) and sl == sizeof(Sockaddr_in).Socklen:
|
||||
address = IpAddress(family: IpAddressFamily.IPv4)
|
||||
let s = cast[ptr Sockaddr_in](sa)
|
||||
copyMem(addr address.address_v4[0], addr s.sin_addr, sizeof(address.address_v4))
|
||||
copyMem(addr address.address_v4[0], addr s.sin_addr,
|
||||
sizeof(address.address_v4))
|
||||
port = ntohs(s.sin_port).Port
|
||||
elif sa.ss_family.int == AF_INET6.int and sl == sizeof(Sockaddr_in6).Socklen:
|
||||
elif sa.ss_family.int == toInt(AF_INET6) and
|
||||
sl == sizeof(Sockaddr_in6).Socklen:
|
||||
address = IpAddress(family: IpAddressFamily.IPv6)
|
||||
let s = cast[ptr Sockaddr_in6](sa)
|
||||
copyMem(addr address.address_v6[0], addr s.sin6_addr, sizeof(address.address_v6))
|
||||
copyMem(addr address.address_v6[0], addr s.sin6_addr,
|
||||
sizeof(address.address_v6))
|
||||
port = ntohs(s.sin6_port).Port
|
||||
else:
|
||||
raise newException(ValueError, "Neither IPv4 nor IPv6")
|
||||
|
|
@ -1149,7 +1156,7 @@ proc waitFor(socket: Socket, waited: var float, timeout, size: int,
|
|||
return 1
|
||||
let sslPending = SSLPending(socket.sslHandle)
|
||||
if sslPending != 0:
|
||||
return sslPending
|
||||
return min(sslPending, size)
|
||||
|
||||
var startTime = epochTime()
|
||||
let selRet = select(socket, timeout - int(waited * 1000.0))
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ when defined(windows):
|
|||
import winlean
|
||||
elif defined(posix):
|
||||
import posix
|
||||
|
||||
proc toTime(ts: Timespec): times.Time {.inline.} =
|
||||
result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
|
||||
|
||||
else:
|
||||
{.error: "OS module not ported to your operating system!".}
|
||||
|
||||
|
|
@ -186,7 +190,7 @@ proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1".}
|
|||
when defined(posix):
|
||||
var res: Stat
|
||||
if stat(file, res) < 0'i32: raiseOSError(osLastError())
|
||||
return fromUnix(res.st_mtime.int64)
|
||||
result = res.st_mtim.toTime
|
||||
else:
|
||||
var f: WIN32_FIND_DATA
|
||||
var h = findFirstFile(file, f)
|
||||
|
|
@ -199,7 +203,7 @@ proc getLastAccessTime*(file: string): times.Time {.rtl, extern: "nos$1".} =
|
|||
when defined(posix):
|
||||
var res: Stat
|
||||
if stat(file, res) < 0'i32: raiseOSError(osLastError())
|
||||
return fromUnix(res.st_atime.int64)
|
||||
result = res.st_atim.toTime
|
||||
else:
|
||||
var f: WIN32_FIND_DATA
|
||||
var h = findFirstFile(file, f)
|
||||
|
|
@ -216,7 +220,7 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} =
|
|||
when defined(posix):
|
||||
var res: Stat
|
||||
if stat(file, res) < 0'i32: raiseOSError(osLastError())
|
||||
return fromUnix(res.st_ctime.int64)
|
||||
result = res.st_ctim.toTime
|
||||
else:
|
||||
var f: WIN32_FIND_DATA
|
||||
var h = findFirstFile(file, f)
|
||||
|
|
@ -228,10 +232,13 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} =
|
|||
## Returns true if the file `a` is newer than file `b`, i.e. if `a`'s
|
||||
## modification time is later than `b`'s.
|
||||
when defined(posix):
|
||||
result = getLastModificationTime(a) - getLastModificationTime(b) >= DurationZero
|
||||
# Posix's resolution sucks so, we use '>=' for posix.
|
||||
# If we don't have access to nanosecond resolution, use '>='
|
||||
when not StatHasNanoseconds:
|
||||
result = getLastModificationTime(a) >= getLastModificationTime(b)
|
||||
else:
|
||||
result = getLastModificationTime(a) > getLastModificationTime(b)
|
||||
else:
|
||||
result = getLastModificationTime(a) - getLastModificationTime(b) > DurationZero
|
||||
result = getLastModificationTime(a) > getLastModificationTime(b)
|
||||
|
||||
proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} =
|
||||
## Returns the `current working directory`:idx:.
|
||||
|
|
@ -1494,7 +1501,7 @@ type
|
|||
|
||||
template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped =
|
||||
## Transforms the native file info structure into the one nim uses.
|
||||
## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows,
|
||||
## 'rawInfo' is either a 'BY_HANDLE_FILE_INFORMATION' structure on Windows,
|
||||
## or a 'Stat' structure on posix
|
||||
when defined(Windows):
|
||||
template merge(a, b): untyped = a or (b shl 32)
|
||||
|
|
@ -1520,7 +1527,6 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped =
|
|||
if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
|
||||
formalInfo.kind = succ(result.kind)
|
||||
|
||||
|
||||
else:
|
||||
template checkAndIncludeMode(rawMode, formalMode: untyped) =
|
||||
if (rawInfo.st_mode and rawMode) != 0'i32:
|
||||
|
|
@ -1528,9 +1534,9 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped =
|
|||
formalInfo.id = (rawInfo.st_dev, rawInfo.st_ino)
|
||||
formalInfo.size = rawInfo.st_size
|
||||
formalInfo.linkCount = rawInfo.st_Nlink.BiggestInt
|
||||
formalInfo.lastAccessTime = fromUnix(rawInfo.st_atime.int64)
|
||||
formalInfo.lastWriteTime = fromUnix(rawInfo.st_mtime.int64)
|
||||
formalInfo.creationTime = fromUnix(rawInfo.st_ctime.int64)
|
||||
formalInfo.lastAccessTime = rawInfo.st_atim.toTime
|
||||
formalInfo.lastWriteTime = rawInfo.st_mtim.toTime
|
||||
formalInfo.creationTime = rawInfo.st_ctim.toTime
|
||||
|
||||
result.permissions = {}
|
||||
checkAndIncludeMode(S_IRUSR, fpUserRead)
|
||||
|
|
@ -1644,7 +1650,9 @@ proc setLastModificationTime*(file: string, t: times.Time) =
|
|||
## an error.
|
||||
when defined(posix):
|
||||
let unixt = posix.Time(t.toUnix)
|
||||
var timevals = [Timeval(tv_sec: unixt), Timeval(tv_sec: unixt)] # [last access, last modification]
|
||||
let micro = convert(Nanoseconds, Microseconds, t.nanosecond)
|
||||
var timevals = [Timeval(tv_sec: unixt, tv_usec: micro),
|
||||
Timeval(tv_sec: unixt, tv_usec: micro)] # [last access, last modification]
|
||||
if utimes(file, timevals.addr) != 0: raiseOSError(osLastError())
|
||||
else:
|
||||
let h = openHandle(path = file, writeAccess = true)
|
||||
|
|
|
|||
|
|
@ -527,8 +527,13 @@ proc format*(value: SomeFloat; specifier: string; res: var string) =
|
|||
var sign = false
|
||||
if value >= 0.0:
|
||||
if spec.sign != '-':
|
||||
f = spec.sign & f
|
||||
sign = true
|
||||
if value == 0.0:
|
||||
if 1.0 / value == Inf:
|
||||
# only insert the sign if value != negZero
|
||||
f.insert($spec.sign, 0)
|
||||
else:
|
||||
f.insert($spec.sign, 0)
|
||||
else:
|
||||
sign = true
|
||||
|
||||
|
|
@ -558,12 +563,16 @@ proc format*(value: string; specifier: string; res: var string) =
|
|||
## sense to call this directly, but it is required to exist
|
||||
## by the ``&`` macro.
|
||||
let spec = parseStandardFormatSpecifier(specifier)
|
||||
var value = value
|
||||
case spec.typ
|
||||
of 's', '\0': discard
|
||||
else:
|
||||
raise newException(ValueError,
|
||||
"invalid type in format string for string, expected 's', but got " &
|
||||
spec.typ)
|
||||
if spec.precision != -1:
|
||||
if spec.precision < runelen(value):
|
||||
setLen(value, runeOffset(value, spec.precision))
|
||||
res.add alignString(value, spec.minimumWidth, spec.align, spec.fill)
|
||||
|
||||
when isMainModule:
|
||||
|
|
|
|||
|
|
@ -185,8 +185,7 @@ type
|
|||
|
||||
DurationParts* = array[FixedTimeUnit, int64] # Array of Duration parts starts
|
||||
TimeIntervalParts* = array[TimeUnit, int] # Array of Duration parts starts
|
||||
|
||||
|
||||
TimesMutableTypes = DateTime | Time | Duration | TimeInterval
|
||||
|
||||
{.deprecated: [TMonth: Month, TWeekDay: WeekDay, TTime: Time,
|
||||
TTimeInterval: TimeInterval, TTimeInfo: DateTime, TimeInfo: DateTime].}
|
||||
|
|
@ -607,30 +606,12 @@ proc `+`*(a: Time, b: Duration): Time {.operator, extern: "ntAddTime".} =
|
|||
doAssert (fromUnix(0) + initDuration(seconds = 1)) == fromUnix(1)
|
||||
addImpl[Time](a, b)
|
||||
|
||||
proc `+=`*(a: var Time, b: Duration) {.operator.} =
|
||||
## Modify ``a`` in place by subtracting ``b``.
|
||||
runnableExamples:
|
||||
var tm = fromUnix(0)
|
||||
tm += initDuration(seconds = 1)
|
||||
doAssert tm == fromUnix(1)
|
||||
|
||||
a = addImpl[Time](a, b)
|
||||
|
||||
proc `-`*(a: Time, b: Duration): Time {.operator, extern: "ntSubTime".} =
|
||||
## Subtracts a duration of time from a ``Time``.
|
||||
runnableExamples:
|
||||
doAssert (fromUnix(0) - initDuration(seconds = 1)) == fromUnix(-1)
|
||||
subImpl[Time](a, b)
|
||||
|
||||
proc `-=`*(a: var Time, b: Duration) {.operator.} =
|
||||
## Modify ``a`` in place by adding ``b``.
|
||||
runnableExamples:
|
||||
var tm = fromUnix(0)
|
||||
tm -= initDuration(seconds = 1)
|
||||
doAssert tm == fromUnix(-1)
|
||||
|
||||
a = subImpl[Time](a, b)
|
||||
|
||||
proc `<`*(a, b: Time): bool {.operator, extern: "ntLtTime".} =
|
||||
## Returns true iff ``a < b``, that is iff a happened before b.
|
||||
ltImpl(a, b)
|
||||
|
|
@ -1377,17 +1358,6 @@ proc `+`*(time: Time, interval: TimeInterval): Time =
|
|||
else:
|
||||
toTime(time.local + interval)
|
||||
|
||||
proc `+=`*(time: var Time, interval: TimeInterval) =
|
||||
## Modifies `time` by adding `interval`.
|
||||
## If `interval` contains any years, months, weeks or days the operation
|
||||
## is performed in the local timezone.
|
||||
runnableExamples:
|
||||
var tm = fromUnix(0)
|
||||
tm += 5.seconds
|
||||
doAssert tm == fromUnix(5)
|
||||
|
||||
time = time + interval
|
||||
|
||||
proc `-`*(time: Time, interval: TimeInterval): Time =
|
||||
## Subtracts `interval` from Time `time`.
|
||||
## If `interval` contains any years, months, weeks or days the operation
|
||||
|
|
@ -1401,15 +1371,30 @@ proc `-`*(time: Time, interval: TimeInterval): Time =
|
|||
else:
|
||||
toTime(time.local - interval)
|
||||
|
||||
proc `-=`*(time: var Time, interval: TimeInterval) =
|
||||
## Modifies `time` by subtracting `interval`.
|
||||
## If `interval` contains any years, months, weeks or days the operation
|
||||
## is performed in the local timezone.
|
||||
proc `+=`*[T, U: TimesMutableTypes](a: var T, b: U) =
|
||||
## Modify ``a`` in place by adding ``b``.
|
||||
runnableExamples:
|
||||
var tm = fromUnix(0)
|
||||
tm += initDuration(seconds = 1)
|
||||
doAssert tm == fromUnix(1)
|
||||
a = a + b
|
||||
|
||||
proc `-=`*[T, U: TimesMutableTypes](a: var T, b: U) =
|
||||
## Modify ``a`` in place by subtracting ``b``.
|
||||
runnableExamples:
|
||||
var tm = fromUnix(5)
|
||||
tm -= 5.seconds
|
||||
tm -= initDuration(seconds = 5)
|
||||
doAssert tm == fromUnix(0)
|
||||
time = time - interval
|
||||
a = a - b
|
||||
|
||||
proc `*=`*[T: TimesMutableTypes, U](a: var T, b: U) =
|
||||
# Mutable type is often multiplied by number
|
||||
runnableExamples:
|
||||
var dur = initDuration(seconds = 1)
|
||||
dur *= 5
|
||||
doAssert dur == initDuration(seconds = 5)
|
||||
|
||||
a = a * b
|
||||
|
||||
proc formatToken(dt: DateTime, token: string, buf: var string) =
|
||||
## Helper of the format proc to parse individual tokens.
|
||||
|
|
|
|||
|
|
@ -2681,7 +2681,7 @@ when not defined(nimscript) and hasAlloc:
|
|||
{.warning: "GC_unref is a no-op in JavaScript".}
|
||||
|
||||
template GC_getStatistics*(): string =
|
||||
{.warning: "GC_disableMarkAndSweep is a no-op in JavaScript".}
|
||||
{.warning: "GC_getStatistics is a no-op in JavaScript".}
|
||||
""
|
||||
|
||||
template accumulateResult*(iter: untyped) =
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
|||
if mode == mStore:
|
||||
x[] = alloc0(t.region, seq.len *% mt.base.size +% GenericSeqSize)
|
||||
else:
|
||||
unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
||||
unsureAsgnRef(x, newSeq(mt, seq.len))
|
||||
var dst = cast[ByteAddress](cast[PPointer](dest)[])
|
||||
var dstseq = cast[PGenericSeq](dst)
|
||||
dstseq.len = seq.len
|
||||
|
|
|
|||
|
|
@ -41,3 +41,6 @@ proc reraiseException() {.compilerRtl.} =
|
|||
proc writeStackTrace() = discard
|
||||
|
||||
proc setControlCHook(hook: proc () {.noconv.}) = discard
|
||||
|
||||
proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
|
||||
sysFatal(ReraiseError, "exception handling is not available")
|
||||
|
|
|
|||
|
|
@ -131,6 +131,10 @@ proc popCurrentExceptionEx(id: uint) {.compilerRtl.} =
|
|||
quitOrDebug()
|
||||
prev.up = cur.up
|
||||
|
||||
proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
|
||||
if not e.isNil:
|
||||
currException = e
|
||||
|
||||
# some platforms have native support for stack traces:
|
||||
const
|
||||
nativeStackTraceSupported* = (defined(macosx) or defined(linux)) and
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue