diff options
author | Konstantin Molchanov <kmolchanov@machinezone.com> | 2016-05-31 12:34:09 +0400 |
---|---|---|
committer | Konstantin Molchanov <kmolchanov@machinezone.com> | 2016-05-31 12:34:09 +0400 |
commit | bea2af7ba2eed9b7c67c5db6586458493c94492b (patch) | |
tree | f3b7342c6375ee738582563ea1e21779e8bc97ed /lib | |
parent | 33f053856611483f52dfaf07c062ca1e646d1083 (diff) | |
parent | f3fdad0eda8664f71e265b7ecc41477a7490331c (diff) | |
download | Nim-bea2af7ba2eed9b7c67c5db6586458493c94492b.tar.gz |
Merge branch 'devel' of github.com:nim-lang/Nim into devel
Diffstat (limited to 'lib')
-rw-r--r-- | lib/core/macros.nim | 2 | ||||
-rw-r--r-- | lib/impure/re.nim | 2 | ||||
-rw-r--r-- | lib/packages/docutils/rst.nim | 13 | ||||
-rw-r--r-- | lib/pure/asynchttpserver.nim | 26 | ||||
-rw-r--r-- | lib/pure/collections/sequtils.nim | 2 | ||||
-rw-r--r-- | lib/pure/concurrency/cpuload.nim | 2 | ||||
-rw-r--r-- | lib/pure/future.nim | 8 | ||||
-rw-r--r-- | lib/pure/httpclient.nim | 3 | ||||
-rw-r--r-- | lib/pure/math.nim | 110 | ||||
-rw-r--r-- | lib/pure/net.nim | 23 | ||||
-rw-r--r-- | lib/pure/parsecfg.nim | 26 | ||||
-rw-r--r-- | lib/pure/parsexml.nim | 4 | ||||
-rw-r--r-- | lib/pure/pegs.nim | 2 | ||||
-rw-r--r-- | lib/pure/random.nim | 129 | ||||
-rw-r--r-- | lib/pure/subexes.nim | 2 | ||||
-rw-r--r-- | lib/pure/times.nim | 107 | ||||
-rw-r--r-- | lib/pure/unittest.nim | 2 | ||||
-rw-r--r-- | lib/system.nim | 2 |
18 files changed, 268 insertions, 197 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim index bfda6b938..16a954611 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -12,7 +12,7 @@ include "system/inclrtl" ## This module contains the interface to the compiler's abstract syntax ## tree (`AST`:idx:). Macros operate on this tree. -## .. include:: ../doc/astspec.txt +## .. include:: ../../doc/astspec.txt type NimNodeKind* = enum diff --git a/lib/impure/re.nim b/lib/impure/re.nim index 60bb6c77f..d49c6d1c1 100644 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -22,7 +22,7 @@ ## though. ## PRCE's licence follows: ## -## .. include:: ../doc/regexprs.txt +## .. include:: ../../doc/regexprs.txt ## import diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index e1d5f902e..ebe6fa19b 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -323,6 +323,11 @@ proc newSharedState(options: RstParseOptions, result.msgHandler = if not isNil(msgHandler): msgHandler else: defaultMsgHandler result.findFile = if not isNil(findFile): findFile else: defaultFindFile +proc findRelativeFile(p: RstParser; filename: string): string = + result = p.filename.splitFile.dir / filename + if not existsFile(result): + result = p.s.findFile(filename) + proc rstMessage(p: RstParser, msgKind: MsgKind, arg: string) = p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line, p.col + p.tok[p.idx].col, msgKind, arg) @@ -1500,7 +1505,7 @@ proc dirInclude(p: var RstParser): PRstNode = result = nil var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil) var filename = strip(addNodes(n.sons[0])) - var path = p.s.findFile(filename) + var path = p.findRelativeFile(filename) if path == "": rstMessage(p, meCannotOpenFile, filename) else: @@ -1511,7 +1516,7 @@ proc dirInclude(p: var RstParser): PRstNode = else: var q: RstParser initParser(q, p.s) - q.filename = filename + q.filename = path q.col += getTokens(readFile(path), false, q.tok) # workaround a GCC bug; more like the interior pointer bug? #if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0: @@ -1538,7 +1543,7 @@ proc dirCodeBlock(p: var RstParser, nimExtension = false): PRstNode = result = parseDirective(p, {hasArg, hasOptions}, parseLiteralBlock) var filename = strip(getFieldValue(result, "file")) if filename != "": - var path = p.s.findFile(filename) + var path = p.findRelativeFile(filename) if path == "": rstMessage(p, meCannotOpenFile, filename) var n = newRstNode(rnLiteralBlock) add(n, newRstNode(rnLeaf, readFile(path))) @@ -1590,7 +1595,7 @@ proc dirRawAux(p: var RstParser, result: var PRstNode, kind: RstNodeKind, contentParser: SectionParser) = var filename = getFieldValue(result, "file") if filename.len > 0: - var path = p.s.findFile(filename) + var path = p.findRelativeFile(filename) if path.len == 0: rstMessage(p, meCannotOpenFile, filename) else: diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 865b14c75..88c3399b0 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -219,20 +219,20 @@ proc processClient(client: AsyncSocket, address: string, else: await client.sendStatus("417 Expectation Failed") - # Read the body - # - Check for Content-length header - if request.headers.hasKey("Content-Length"): - var contentLength = 0 - if parseInt(request.headers.getOrDefault("Content-Length"), - contentLength) == 0: - await request.respond(Http400, "Bad Request. Invalid Content-Length.") - continue - else: - request.body = await client.recv(contentLength) - assert request.body.len == contentLength - else: - await request.respond(Http400, "Bad Request. No Content-Length.") + # Read the body + # - Check for Content-length header + if request.headers.hasKey("Content-Length"): + var contentLength = 0 + if parseInt(request.headers.getOrDefault("Content-Length"), + contentLength) == 0: + await request.respond(Http400, "Bad Request. Invalid Content-Length.") continue + else: + request.body = await client.recv(contentLength) + assert request.body.len == contentLength + else: + await request.respond(Http400, "Bad Request. No Content-Length.") + continue case request.reqMethod of "get", "post", "head", "put", "delete", "trace", "options", diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 0e3824a81..0817b38a3 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -657,7 +657,7 @@ template newSeqWith*(len: int, init: expr): expr = ## seq2D[1][0] = true ## seq2D[0][1] = true ## - ## import math + ## import random ## var seqRand = newSeqWith(20, random(10)) ## echo seqRand var result {.gensym.} = newSeq[type(init)](len) diff --git a/lib/pure/concurrency/cpuload.nim b/lib/pure/concurrency/cpuload.nim index 22598b5c9..b0fd002ed 100644 --- a/lib/pure/concurrency/cpuload.nim +++ b/lib/pure/concurrency/cpuload.nim @@ -79,6 +79,8 @@ proc advice*(s: var ThreadPoolState): ThreadPoolAdvice = inc s.calls when not defined(testing) and isMainModule: + import random + proc busyLoop() = while true: discard random(80) diff --git a/lib/pure/future.nim b/lib/pure/future.nim index 3793edc8b..4e2c1d893 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -29,21 +29,17 @@ proc createProcType(p, b: NimNode): NimNode {.compileTime.} = of nnkExprColonExpr: identDefs.add ident[0] identDefs.add ident[1] - of nnkIdent: + else: identDefs.add newIdentNode("i" & $i) identDefs.add(ident) - else: - error("Incorrect type list in proc type declaration.") identDefs.add newEmptyNode() formalParams.add identDefs - of nnkIdent: + else: var identDefs = newNimNode(nnkIdentDefs) identDefs.add newIdentNode("i0") identDefs.add(p) identDefs.add newEmptyNode() formalParams.add identDefs - else: - error("Incorrect type list in proc type declaration.") result.add formalParams result.add newEmptyNode() diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 040ce10da..d59b8ecfe 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -79,7 +79,8 @@ ## constructor should be used for this purpose. However, ## currently only basic authentication is supported. -import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math +import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, + math, random import asyncnet, asyncdispatch import nativesockets diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 2feaef097..ce418d72c 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -39,8 +39,6 @@ proc fac*(n: int): int {.noSideEffect.} = when defined(Posix) and not defined(haiku): {.passl: "-lm".} -when not defined(js) and not defined(nimscript): - import times const PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number) @@ -119,30 +117,6 @@ proc sum*[T](x: openArray[T]): T {.noSideEffect.} = ## If `x` is empty, 0 is returned. for i in items(x): result = result + i -proc random*(max: int): int {.benign.} - ## Returns a random number in the range 0..max-1. The sequence of - ## random number is always the same, unless `randomize` is called - ## which initializes the random number generator with a "random" - ## number, i.e. a tickcount. - -proc random*(max: 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" - ## number, i.e. a tickcount. This has a 16-bit resolution on windows - ## and a 48-bit resolution on other platforms. - -when not defined(nimscript): - proc randomize*() {.benign.} - ## Initializes the random number generator with a "random" - ## number, i.e. a tickcount. Note: Does nothing for the JavaScript target, - ## as JavaScript does not support this. Nor does it work for NimScript. - -proc randomize*(seed: int) {.benign.} - ## Initializes the random number generator with a specific seed. - ## Note: Does nothing for the JavaScript target, - ## as JavaScript does not support this. - {.push noSideEffect.} when not defined(JS): proc sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".} @@ -239,57 +213,6 @@ when not defined(JS): proc tgamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".} ## The gamma function - # C procs: - when defined(vcc) and false: - # The "secure" random, available from Windows XP - # https://msdn.microsoft.com/en-us/library/sxtz2fa8.aspx - # Present in some variants of MinGW but not enough to justify - # `when defined(windows)` yet - proc rand_s(val: var cuint) {.importc: "rand_s", header: "<stdlib.h>".} - # To behave like the normal version - proc rand(): cuint = rand_s(result) - else: - proc srand(seed: cint) {.importc: "srand", header: "<stdlib.h>".} - proc rand(): cint {.importc: "rand", header: "<stdlib.h>".} - - when not defined(windows): - proc srand48(seed: clong) {.importc: "srand48", header: "<stdlib.h>".} - proc drand48(): float {.importc: "drand48", header: "<stdlib.h>".} - proc random(max: float): float = - result = drand48() * max - else: - when defined(vcc): # Windows with Visual C - proc random(max: float): float = - # we are hardcoding this because - # importc-ing macros is extremely problematic - # and because the value is publicly documented - # on MSDN and very unlikely to change - # See https://msdn.microsoft.com/en-us/library/296az74e.aspx - const rand_max = 4294967295 # UINT_MAX - result = (float(rand()) / float(rand_max)) * max - proc randomize() = discard - proc randomize(seed: int) = discard - else: # Windows with another compiler - proc random(max: float): float = - # we are hardcoding this because - # importc-ing macros is extremely problematic - # and because the value is publicly documented - # on MSDN and very unlikely to change - const rand_max = 32767 - result = (float(rand()) / float(rand_max)) * max - - when not defined(vcc): # the above code for vcc uses `discard` instead - # this is either not Windows or is Windows without vcc - when not defined(nimscript): - proc randomize() = - randomize(cast[int](epochTime())) - proc randomize(seed: int) = - srand(cint(seed)) # rand_s doesn't use srand - when declared(srand48): srand48(seed) - - proc random(max: int): int = - result = int(rand()) mod max - proc trunc*(x: float32): float32 {.importc: "truncf", header: "<math.h>".} proc trunc*(x: float64): float64 {.importc: "trunc", header: "<math.h>".} ## Truncates `x` to the decimal point @@ -319,17 +242,10 @@ when not defined(JS): ## echo fmod(-2.5, 0.3) ## -0.1 else: - proc mathrandom(): float {.importc: "Math.random", nodecl.} proc floor*(x: float32): float32 {.importc: "Math.floor", nodecl.} proc floor*(x: float64): float64 {.importc: "Math.floor", nodecl.} proc ceil*(x: float32): float32 {.importc: "Math.ceil", nodecl.} proc ceil*(x: float64): float64 {.importc: "Math.ceil", nodecl.} - proc random(max: int): int = - result = int(floor(mathrandom() * float(max))) - proc random(max: float): float = - result = float(mathrandom() * float(max)) - proc randomize() = discard - proc randomize(seed: int) = discard proc sqrt*(x: float32): float32 {.importc: "Math.sqrt", nodecl.} proc sqrt*(x: float64): float64 {.importc: "Math.sqrt", nodecl.} @@ -398,14 +314,6 @@ proc `mod`*[T: float32|float64](x, y: T): T = ## echo (4.0 mod -3.1) # -2.2 result = if y == 0.0: x else: x - y * (x/y).floor -proc random*[T](x: Slice[T]): T = - ## For a slice `a .. b` returns a value in the range `a .. b-1`. - result = random(x.b - x.a) + x.a - -proc random*[T](a: openArray[T]): T = - ## returns a random element from the openarray `a`. - result = a[random(a.low..a.len)] - {.pop.} {.pop.} @@ -440,24 +348,6 @@ proc lcm*[T](x, y: T): T = x div gcd(x, y) * y when isMainModule and not defined(JS): - proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".} - - # Verifies random seed initialization. - let seed = gettime(nil) - randomize(seed) - const SIZE = 10 - var buf : array[0..SIZE, int] - # Fill the buffer with random values - for i in 0..SIZE-1: - buf[i] = random(high(int)) - # Check that the second random calls are the same for each position. - randomize(seed) - for i in 0..SIZE-1: - assert buf[i] == random(high(int)), "non deterministic random seeding" - - when not defined(testing): - echo "random values equal after reseeding" - # Check for no side effect annotation proc mySqrt(num: float): float {.noSideEffect.} = return sqrt(num) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index c734fe893..cb8cea720 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -606,28 +606,31 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) { var valuei = cint(if value: 1 else: 0) setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei) -when defined(posix) or defined(nimdoc): +when defined(posix) and not defined(nimdoc): proc makeUnixAddr(path: string): Sockaddr_un = result.sun_family = AF_UNIX.toInt if path.len >= Sockaddr_un_path_length: raise newException(ValueError, "socket path too long") copyMem(addr result.sun_path, path.cstring, path.len + 1) +when defined(posix): proc connectUnix*(socket: Socket, path: string) = ## Connects to Unix socket on `path`. ## This only works on Unix-style systems: Mac OS X, BSD and Linux - var socketAddr = makeUnixAddr(path) - if socket.fd.connect(cast[ptr SockAddr](addr socketAddr), - sizeof(socketAddr).Socklen) != 0'i32: - raiseOSError(osLastError()) + when not defined(nimdoc): + var socketAddr = makeUnixAddr(path) + if socket.fd.connect(cast[ptr SockAddr](addr socketAddr), + sizeof(socketAddr).Socklen) != 0'i32: + raiseOSError(osLastError()) proc bindUnix*(socket: Socket, path: string) = ## Binds Unix socket to `path`. ## This only works on Unix-style systems: Mac OS X, BSD and Linux - var socketAddr = makeUnixAddr(path) - if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), - sizeof(socketAddr).Socklen) != 0'i32: - raiseOSError(osLastError()) + when not defined(nimdoc): + var socketAddr = makeUnixAddr(path) + if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), + sizeof(socketAddr).Socklen) != 0'i32: + raiseOSError(osLastError()) when defined(ssl): proc handshake*(socket: Socket): bool @@ -1399,7 +1402,7 @@ proc connect*(socket: Socket, address: string, port = Port(0), if selectWrite(s, timeout) != 1: raise newException(TimeoutError, "Call to 'connect' timed out.") else: - when defineSsl: + when defineSsl and not defined(nimdoc): if socket.isSSL: socket.fd.setBlocking(true) {.warning[Deprecated]: off.} diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index bf19d5540..25879d2b7 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -15,21 +15,21 @@ ## This is an example of how a configuration file may look like: ## -## .. include:: doc/mytest.cfg +## .. include:: ../../doc/mytest.cfg ## :literal: ## The file ``examples/parsecfgex.nim`` demonstrates how to use the ## configuration file parser: ## ## .. code-block:: nim -## :file: examples/parsecfgex.nim -## +## :file: ../../examples/parsecfgex.nim +## ## Examples ## -------- ## ## This is an example of a configuration file. -## -## .. include:: config.ini -## +## +## :: +## ## charset = "utf-8" ## [Package] ## name = "hello" @@ -38,11 +38,11 @@ ## name = "lihf8515" ## qq = "10214028" ## email = "lihaifeng@wxm.com" -## +## ## Creating a configuration file. ## ============================== ## .. code-block:: nim -## +## ## import parsecfg ## var dict=newConfig() ## dict.setSectionKey("","charset","utf-8") @@ -52,7 +52,7 @@ ## dict.setSectionKey("Author","qq","10214028") ## dict.setSectionKey("Author","email","lihaifeng@wxm.com") ## dict.writeConfig("config.ini") -## +## ## Reading a configuration file. ## ============================= ## .. code-block:: nim @@ -66,11 +66,11 @@ ## var qq = dict.getSectionValue("Author","qq") ## var email = dict.getSectionValue("Author","email") ## echo pname & "\n" & name & "\n" & qq & "\n" & email -## +## ## Modifying a configuration file. ## =============================== ## .. code-block:: nim -## +## ## import parsecfg ## var dict = loadConfig("config.ini") ## dict.setSectionKey("Author","name","lhf") @@ -79,7 +79,7 @@ ## Deleting a section key in a configuration file. ## =============================================== ## .. code-block:: nim -## +## ## import parsecfg ## var dict = loadConfig("config.ini") ## dict.delSectionKey("Author","email") @@ -434,7 +434,7 @@ proc loadConfig*(filename: string): Config = ## Load the specified configuration file into a new Config instance. var dict = newOrderedTable[string, OrderedTableRef[string, string]]() var curSection = "" ## Current section, - ## the default value of the current section is "", + ## the default value of the current section is "", ## which means that the current section is a common var p: CfgParser var fileStream = newFileStream(filename, fmRead) diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim index f8b2c3d8d..06daa3782 100644 --- a/lib/pure/parsexml.nim +++ b/lib/pure/parsexml.nim @@ -34,7 +34,7 @@ ## document. ## ## .. code-block:: nim -## :file: examples/htmltitle.nim +## :file: ../../examples/htmltitle.nim ## ## ## Example 2: Retrieve all HTML links @@ -45,7 +45,7 @@ ## an HTML document contains. ## ## .. code-block:: nim -## :file: examples/htmlrefs.nim +## :file: ../../examples/htmlrefs.nim ## import diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index eea20a62c..7e1f50266 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -12,7 +12,7 @@ ## Matching performance is hopefully competitive with optimized regular ## expression engines. ## -## .. include:: ../doc/pegdocs.txt +## .. include:: ../../doc/pegdocs.txt ## include "system/inclrtl" diff --git a/lib/pure/random.nim b/lib/pure/random.nim new file mode 100644 index 000000000..c73f403eb --- /dev/null +++ b/lib/pure/random.nim @@ -0,0 +1,129 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2016 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +##[Nim's standard random number generator. Based on + +| `http://xoroshiro.di.unimi.it/`_ +| `http://xoroshiro.di.unimi.it/xoroshiro128plus.c`_ +]## + +include "system/inclrtl" +{.push debugger:off.} + +# XXX Expose RandomGenState +when defined(JS): + type ui = uint32 +else: + type ui = uint64 + +type + RandomGenState = object + a0, a1: ui + +when defined(JS): + var state = RandomGenState( + a0: 0x69B4C98Cu32, + a1: 0xFED1DD30u32) # global for backwards compatibility +else: + # racy for multi-threading but good enough for now: + var state = RandomGenState( + a0: 0x69B4C98CB8530805u64, + a1: 0xFED1DD3004688D67CAu64) # global for backwards compatibility + +proc rotl(x, k: ui): ui = + result = (x shl k) or (x shr (ui(64) - k)) + +proc next(s: var RandomGenState): uint64 = + let s0 = s.a0 + var s1 = s.a1 + result = s0 + s1 + s1 = s1 xor s0 + s.a0 = rotl(s0, 55) xor s1 xor (s1 shl 14) # a, b + s.a1 = rotl(s1, 36) # c + +proc skipRandomNumbers(s: var RandomGenState) = + ## This is the jump function for the generator. It is equivalent + ## to 2^64 calls to next(); it can be used to generate 2^64 + ## non-overlapping subsequences for parallel computations. + when defined(JS): + const helper = [0xbeac0467u32, 0xd86b048bu32] + else: + const helper = [0xbeac0467eba5facbu64, 0xd86b048b86aa9922u64] + var + s0 = ui 0 + s1 = ui 0 + for i in 0..high(helper): + for b in 0..< 64: + if (helper[i] and (ui(1) shl ui(b))) != 0: + s0 = s0 xor s.a0 + s1 = s1 xor s.a1 + discard next(s) + s.a0 = s0 + s.a1 = s1 + +proc random*(max: int): int {.benign.} = + ## Returns a random number in the range 0..max-1. The sequence of + ## random number is always the same, unless `randomize` is called + ## which initializes the random number generator with a "random" + ## number, i.e. a tickcount. + result = int(next(state) mod uint64(max)) + +proc random*(max: 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" + ## number, i.e. a tickcount. + let x = next(state) + when defined(JS): + result = (float(x) / float(high(uint32))) * max + else: + let u = (0x3FFu64 shl 52u64) or (x shr 12u64) + result = (cast[float](u) - 1.0) * max + +proc random*[T](x: Slice[T]): T = + ## For a slice `a .. b` returns a value in the range `a .. b-1`. + result = random(x.b - x.a) + x.a + +proc random*[T](a: openArray[T]): T = + ## returns a random element from the openarray `a`. + result = a[random(a.low..a.len)] + +proc randomize*(seed: int) {.benign.} = + ## Initializes the random number generator with a specific seed. + state.a0 = ui(seed shr 16) + state.a1 = ui(seed and 0xffff) + +when not defined(nimscript): + import times + + proc randomize*() {.benign.} = + ## Initializes the random number generator with a "random" + ## number, i.e. a tickcount. Note: Does not work for NimScript. + when defined(JS): + proc getMil(t: Time): int {.importcpp: "getTime", nodecl.} + randomize(getMil times.getTime()) + else: + randomize(int times.getTime()) + +{.pop.} + +when isMainModule: + proc main = + var occur: array[1000, int] + + var x = 8234 + for i in 0..100_000: + x = random(len(occur)) # myrand(x) + inc occur[x] + for i, oc in occur: + if oc < 69: + doAssert false, "too few occurances of " & $i + elif oc > 130: + doAssert false, "too many occurances of " & $i + main() diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index 22f29b77c..351b3c086 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -9,7 +9,7 @@ ## Nim support for `substitution expressions`:idx: (`subex`:idx:). ## -## .. include:: ../doc/subexes.txt +## .. include:: ../../doc/subexes.txt ## {.push debugger:off .} # the user does not want to trace a part diff --git a/lib/pure/times.nim b/lib/pure/times.nim index e0ee884a8..f9d341e32 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -64,8 +64,9 @@ when defined(posix) and not defined(JS): proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {. importc: "gettimeofday", header: "<sys/time.h>".} - var - timezone {.importc, header: "<time.h>".}: int + when not defined(freebsd) and not defined(netbsd) and not defined(openbsd): + var timezone {.importc, header: "<time.h>".}: int + var tzname {.importc, header: "<time.h>" .}: array[0..1, cstring] # we also need tzset() to make sure that tzname is initialized proc tzset() {.importc, header: "<time.h>".} @@ -416,18 +417,32 @@ when not defined(JS): when not defined(JS): # C wrapper: + when defined(freebsd) or defined(netbsd) or defined(openbsd): + type + StructTM {.importc: "struct tm", final.} = object + second {.importc: "tm_sec".}, + minute {.importc: "tm_min".}, + hour {.importc: "tm_hour".}, + monthday {.importc: "tm_mday".}, + month {.importc: "tm_mon".}, + year {.importc: "tm_year".}, + weekday {.importc: "tm_wday".}, + yearday {.importc: "tm_yday".}, + isdst {.importc: "tm_isdst".}: cint + gmtoff {.importc: "tm_gmtoff".}: clong + else: + type + StructTM {.importc: "struct tm", final.} = object + second {.importc: "tm_sec".}, + minute {.importc: "tm_min".}, + hour {.importc: "tm_hour".}, + monthday {.importc: "tm_mday".}, + month {.importc: "tm_mon".}, + year {.importc: "tm_year".}, + weekday {.importc: "tm_wday".}, + yearday {.importc: "tm_yday".}, + isdst {.importc: "tm_isdst".}: cint type - StructTM {.importc: "struct tm", final.} = object - second {.importc: "tm_sec".}, - minute {.importc: "tm_min".}, - hour {.importc: "tm_hour".}, - monthday {.importc: "tm_mday".}, - month {.importc: "tm_mon".}, - year {.importc: "tm_year".}, - weekday {.importc: "tm_wday".}, - yearday {.importc: "tm_yday".}, - isdst {.importc: "tm_isdst".}: cint - TimeInfoPtr = ptr StructTM Clock {.importc: "clock_t".} = distinct int @@ -457,24 +472,47 @@ when not defined(JS): const weekDays: array [0..6, WeekDay] = [ dSun, dMon, dTue, dWed, dThu, dFri, dSat] - TimeInfo(second: int(tm.second), - minute: int(tm.minute), - hour: int(tm.hour), - monthday: int(tm.monthday), - month: Month(tm.month), - year: tm.year + 1900'i32, - weekday: weekDays[int(tm.weekday)], - yearday: int(tm.yearday), - isDST: tm.isdst > 0, - tzname: if local: - if tm.isdst > 0: - getTzname().DST + when defined(freebsd) or defined(netbsd) or defined(openbsd): + TimeInfo(second: int(tm.second), + minute: int(tm.minute), + hour: int(tm.hour), + monthday: int(tm.monthday), + month: Month(tm.month), + year: tm.year + 1900'i32, + weekday: weekDays[int(tm.weekday)], + yearday: int(tm.yearday), + isDST: tm.isdst > 0, + tzname: if local: + if tm.isdst > 0: + getTzname().DST + else: + getTzname().nonDST else: - getTzname().nonDST - else: - "UTC", - timezone: if local: getTimezone() else: 0 - ) + "UTC", + # BSD stores in `gmtoff` offset east of UTC in seconds, + # but posix systems using west of UTC in seconds + timezone: if local: -(tm.gmtoff) else: 0 + ) + else: + TimeInfo(second: int(tm.second), + minute: int(tm.minute), + hour: int(tm.hour), + monthday: int(tm.monthday), + month: Month(tm.month), + year: tm.year + 1900'i32, + weekday: weekDays[int(tm.weekday)], + yearday: int(tm.yearday), + isDST: tm.isdst > 0, + tzname: if local: + if tm.isdst > 0: + getTzname().DST + else: + getTzname().nonDST + else: + "UTC", + timezone: if local: getTimezone() else: 0 + ) + proc timeInfoToTM(t: TimeInfo): StructTM = const @@ -564,7 +602,14 @@ when not defined(JS): return ($tzname[0], $tzname[1]) proc getTimezone(): int = - return timezone + when defined(freebsd) or defined(netbsd) or defined(openbsd): + var a = timec(nil) + let lt = localtime(addr(a)) + # BSD stores in `gmtoff` offset east of UTC in seconds, + # but posix systems using west of UTC in seconds + return -(lt.gmtoff) + else: + return timezone proc fromSeconds(since1970: float): Time = Time(since1970) diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index aca9d51e2..b83ec44ca 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -310,7 +310,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} = ## ## .. code-block:: nim ## - ## import math + ## import math, random ## proc defectiveRobot() = ## randomize() ## case random(1..4) diff --git a/lib/system.nim b/lib/system.nim index c224535f0..8180f27cd 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2514,7 +2514,7 @@ template newException*(exceptn: typedesc, message: string): expr = e when hostOS == "standalone": - include panicoverride + include "$projectpath/panicoverride" when not declared(sysFatal): when hostOS == "standalone": |