Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Konstantin Molchanov 2016-05-31 12:34:09 +04:00
commit bea2af7ba2
49 changed files with 379 additions and 254 deletions

View file

@ -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",

View file

@ -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)

View file

@ -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)

View file

@ -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()

View file

@ -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

View file

@ -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)

View file

@ -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.}

View file

@ -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)

View file

@ -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

View file

@ -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"

129
lib/pure/random.nim Normal file
View file

@ -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()

View file

@ -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

View file

@ -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)

View file

@ -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)