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
49 changed files with 379 additions and 254 deletions

View File

@@ -938,7 +938,7 @@ const
genericParamsPos* = 2
paramsPos* = 3
pragmasPos* = 4
optimizedCodePos* = 5 # will be used for exception tracking
miscPos* = 5 # used for undocumented and hacky stuff
bodyPos* = 6 # position of body; use rodread.getBody() instead!
resultPos* = 7
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 7!

View File

@@ -262,13 +262,7 @@ proc processPath(path: string, info: TLineInfo,
else:
options.gProjectPath / path
try:
result = unixToNativePath(p % ["nimrod", getPrefixDir(),
"nim", getPrefixDir(),
"lib", libpath,
"home", removeTrailingDirSep(os.getHomeDir()),
"config", info.toFullPath().splitFile().dir,
"projectname", options.gProjectName,
"projectpath", options.gProjectPath])
result = pathSubs(p, info.toFullPath().splitFile().dir)
except ValueError:
localError(info, "invalid path: " & p)
result = p
@@ -322,6 +316,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
of "nonimblepath", "nobabelpath":
expectNoArg(switch, arg, pass, info)
options.gNoNimblePath = true
options.lazyPaths.head = nil
options.lazyPaths.tail = nil
options.lazyPaths.counter = 0
of "excludepath":
expectArg(switch, arg, pass, info)
let path = processPath(arg, info)

View File

@@ -22,7 +22,11 @@ proc getModuleName*(n: PNode): string =
# The proc won't perform any checks that the path is actually valid
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
result = unixToNativePath(n.strVal)
try:
result = pathSubs(n.strVal, n.info.toFullPath().splitFile().dir)
except ValueError:
localError(n.info, "invalid path: " & n.strVal)
result = n.strVal
of nkIdent:
result = n.ident.s
of nkSym:

View File

@@ -242,7 +242,7 @@ proc mainCommand* =
clearPasses()
gLastCmdTime = epochTime()
appendStr(searchPaths, options.libpath)
if gProjectFull.len != 0:
when false: # gProjectFull.len != 0:
# current path is always looked first for modules
prependStr(searchPaths, gProjectPath)
setId(100)

View File

@@ -7,7 +7,7 @@ path:"$projectPath/.."
path:"$lib/packages/docutils"
define:booting
import:testability
#import:"$projectpath/testability"
@if windows:
cincludes: "$lib/wrappers/libffi/common"

View File

@@ -242,6 +242,21 @@ proc getNimcacheDir*: string =
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
genSubDir
proc pathSubs*(p, config: string): string =
let home = removeTrailingDirSep(os.getHomeDir())
result = unixToNativePath(p % [
"nim", getPrefixDir(),
"lib", libpath,
"home", home,
"config", config,
"projectname", options.gProjectName,
"projectpath", options.gProjectPath,
"projectdir", options.gProjectPath,
"nimcache", getNimcacheDir()])
if '~' in result:
result = result.replace("~", home)
template newPackageCache(): expr =
newStringTable(when FileSystemCaseSensitive:
modeCaseInsensitive

View File

@@ -393,21 +393,23 @@ type
TLinkFeature = enum
linkNormal, linkSys
proc processCompile(c: PContext, n: PNode) =
proc relativeFile(c: PContext; n: PNode; ext=""): string =
var s = expectStrLit(c, n)
var found = findFile(s)
if found == "": found = s
var trunc = changeFileExt(found, "")
if not isAbsolute(found):
found = parentDir(n.info.toFullPath) / found
if ext.len > 0 and splitFile(s).ext == "":
s = addFileExt(s, ext)
result = parentDir(n.info.toFullPath) / s
if not fileExists(result):
if isAbsolute(s): result = s
else: result = findFile(s)
proc processCompile(c: PContext, n: PNode) =
let found = relativeFile(c, n)
let trunc = found.changeFileExt("")
extccomp.addExternalFileToCompile(found)
extccomp.addFileToLink(completeCFilePath(trunc, false))
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
var f = expectStrLit(c, n)
if splitFile(f).ext == "": f = addFileExt(f, CC[cCompiler].objExt)
var found = findFile(f)
if found == "": found = f # use the default
let found = relativeFile(c, n, CC[cCompiler].objExt)
case feature
of linkNormal: extccomp.addFileToLink(found)
of linkSys:

View File

@@ -712,7 +712,11 @@ proc gproc(g: var TSrcGen, n: PNode) =
gpattern(g, n.sons[patternPos])
let oldCheckAnon = g.checkAnon
g.checkAnon = true
gsub(g, n.sons[genericParamsPos])
if renderNoBody in g.flags and n[miscPos].kind != nkEmpty and
n[miscPos][1].kind != nkEmpty:
gsub(g, n[miscPos][1])
else:
gsub(g, n.sons[genericParamsPos])
g.checkAnon = oldCheckAnon
gsub(g, n.sons[paramsPos])
gsub(g, n.sons[pragmasPos])

View File

@@ -129,7 +129,11 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
add(result, ')')
var candidates = ""
for err in errors:
add(candidates, err.getProcHeader(prefer))
if err.kind in routineKinds and err.ast != nil:
add(candidates, renderTree(err.ast,
{renderNoBody, renderNoComments,renderNoPragmas}))
else:
add(candidates, err.getProcHeader(prefer))
add(candidates, "\n")
if candidates != "":
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)

View File

@@ -929,6 +929,17 @@ proc semProcAnnotation(c: PContext, prc: PNode;
pragma(c, result[namePos].sym, result[pragmasPos], validPragmas)
return
proc setGenericParamsMisc(c: PContext; n: PNode): PNode =
let orig = n.sons[genericParamsPos]
# we keep the original params around for better error messages, see
# issue https://github.com/nim-lang/Nim/issues/1713
result = semGenericParamList(c, orig)
if n.sons[miscPos].kind == nkEmpty:
n.sons[miscPos] = newTree(nkBracket, ast.emptyNode, orig)
else:
n.sons[miscPos].sons[1] = orig
n.sons[genericParamsPos] = result
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
# XXX semProcAux should be good enough for this now, we will eventually
# remove semLambda
@@ -947,8 +958,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
openScope(c)
var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty:
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
gp = n.sons[genericParamsPos]
gp = setGenericParamsMisc(c, n)
else:
gp = newNodeI(nkGenericParams, n.info)
@@ -1170,8 +1180,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
openScope(c)
var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty:
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
gp = n.sons[genericParamsPos]
gp = setGenericParamsMisc(c, n)
else:
gp = newNodeI(nkGenericParams, n.info)
# process parameters:

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
import ast, types, msgs, osproc, streams, options, idents, securehash
import ast, types, msgs, os, osproc, streams, options, idents, securehash
proc readOutput(p: Process): string =
result = ""
@@ -51,7 +51,9 @@ proc opGorge*(cmd, input, cache: string): string =
proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
try:
let filename = file.findFile
var filename = parentDir(info.toFullPath) / file
if not fileExists(filename):
filename = file.findFile
result = readFile(filename)
# we produce a fake include statement for every slurped filename, so that
# the module dependencies are accurate:

View File

@@ -1887,8 +1887,8 @@ proc optimizeJumps(c: PCtx; start: int) =
else: discard
proc genProc(c: PCtx; s: PSym): int =
let x = s.ast.sons[optimizedCodePos]
if x.kind == nkEmpty:
var x = s.ast.sons[miscPos]
if x.kind == nkEmpty or x[0].kind == nkEmpty:
#if s.name.s == "outterMacro" or s.name.s == "innerProc":
# echo "GENERATING CODE FOR ", s.name.s
let last = c.code.len-1
@@ -1899,7 +1899,11 @@ proc genProc(c: PCtx; s: PSym): int =
c.debug.setLen(last)
#c.removeLastEof
result = c.code.len+1 # skip the jump instruction
s.ast.sons[optimizedCodePos] = newIntNode(nkIntLit, result)
if x.kind == nkEmpty:
x = newTree(nkBracket, newIntNode(nkIntLit, result), ast.emptyNode)
else:
x.sons[0] = newIntNode(nkIntLit, result)
s.ast.sons[miscPos] = x
# thanks to the jmp we can add top level statements easily and also nest
# procs easily:
let body = s.getBody
@@ -1934,4 +1938,4 @@ proc genProc(c: PCtx; s: PSym): int =
c.prc = oldPrc
else:
c.prc.maxSlots = s.offset
result = x.intVal.int
result = x[0].intVal.int

View File

@@ -202,6 +202,9 @@ Math libraries
* `mersenne <mersenne.html>`_
Mersenne twister random number generator.
* `random <random.html>`_
Fast and tiny random number generator.
* `stats <stats.html>`_
Statistical analysis

View File

@@ -155,4 +155,4 @@ Exception hierarchy
The exception tree is defined in the `system <system.html>`_ module:
.. include:: exception_hierarchy_fragment.txt
.. include:: ../exception_hierarchy_fragment.txt

View File

@@ -116,7 +116,7 @@ operator characters instead.
The following keywords are reserved and cannot be used as identifiers:
.. code-block:: nim
:file: keywords.txt
:file: ../keywords.txt
Some keywords are unused; they are reserved for future developments of the
language.

View File

@@ -119,6 +119,6 @@ Grammar
The grammar's start symbol is ``module``.
.. include:: grammar.txt
.. include:: ../grammar.txt
:literal:

View File

@@ -694,7 +694,7 @@ branch switch ``system.reset`` has to be used.
Set type
--------
.. include:: sets_fragment.txt
.. include:: ../sets_fragment.txt
Reference and pointer types
---------------------------

View File

@@ -27,7 +27,7 @@ Configuration file
niminst uses the Nim `parsecfg <parsecfg.html>`_ module to parse the
configuration file. Here's an example of how the syntax looks like:
.. include:: doc/mytest.cfg
.. include:: mytest.cfg
:literal:
The value of a key-value pair can reference user-defined variables via
@@ -190,6 +190,6 @@ Real world example
The installers for the Nim compiler itself are generated by niminst. Have a
look at its configuration file:
.. include:: compiler/installer.ini
.. include:: ../compiler/installer.ini
:literal:

View File

@@ -336,10 +336,11 @@ template `|`(a, b): expr = (if a.len > 0: a else: b)
proc tests(args: string) =
# we compile the tester with taintMode:on to have a basic
# taint mode test :-)
exec "nim cc --taintMode:on tests/testament/tester"
let nimexe = findNim()
exec nimexe & " cc --taintMode:on tests/testament/tester"
# Since tests take a long time (on my machine), and we want to defy Murhpys
# law - lets make sure the compiler really is freshly compiled!
exec "nim c --lib:lib -d:release --opt:speed compiler/nim.nim"
exec nimexe & " c --lib:lib -d:release --opt:speed compiler/nim.nim"
let tester = quoteShell(getCurrentDir() / "tests/testament/tester".exe)
let success = tryExec tester & " " & (args|"all")
if not existsEnv("TRAVIS") and not existsEnv("APPVEYOR"):

View File

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

View File

@@ -22,7 +22,7 @@
## though.
## PRCE's licence follows:
##
## .. include:: ../doc/regexprs.txt
## .. include:: ../../doc/regexprs.txt
##
import

View File

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

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)

View File

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

View File

@@ -2,7 +2,7 @@ discard """
action: run
"""
import math, strutils
import math, random, strutils
const consolePrefix = "jsCallbacks"
asm """

View File

@@ -1,6 +1,6 @@
import
sfml, chipmunk,
sg_assets, sfml_stuff, keineschweine
sg_assets, sfml_stuff, "../keineschweine"
proc accel*(obj: PVehicle, dt: float) =

View File

@@ -1,5 +1,5 @@
import nake
import httpclient, zip/zipfiles, times, math, sequtils
import httpclient, zip/zipfiles, times, random, sequtils
nakeImports
randomize()
@@ -145,7 +145,7 @@ task "download", "download game assets":
echo "Extracted the libs dir. Copy the ones you need to this dir."
task "zip-lib", "zip up the libs dir":
var z: TZipArchive
var z: ZipArchive
if not z.open("libs-" & getDateStr() & ".zip", fmReadWrite):
quit "Could not open zip"
for file in walkDirRec("libs", {pcFile, pcDir}):

View File

@@ -1,2 +1,3 @@
# this file only exists to mark 'main.nim' as the main file
--path:"$projectpath"

View File

@@ -1,6 +1,6 @@
import
tri_engine/config,
tri_engine/math/vec
../config,
vec
type
TCircle* = tuple[p: TV2[TR], r: TR]

View File

@@ -1,6 +1,6 @@
import
macros,
tri_engine/config
"../config"
type
TV2*[T:SomeNumber=TR] = array[0..1, T]

View File

@@ -2,7 +2,7 @@ discard """
output: "Success"
"""
import math, threadPool
import math, random, threadPool
# ---

View File

@@ -1,4 +1,4 @@
import math
import math, random
import unittest
import sets

View File

@@ -26,7 +26,7 @@ test "unittest multiple requires":
require(true)
import math
import math, random
from strutils import parseInt
proc defectiveRobot() =
randomize()

View File

@@ -4,7 +4,7 @@ discard """
# bug #1816
from math import random
from random import random
from os import sleep
type PComm = ptr Channel[int]

View File

@@ -2,7 +2,7 @@
News
====
2016-XX-XX Version 0.13.1 released
2016-XX-XX Version 0.14.0 released
==================================
Changes affecting backwards compatibility
@@ -39,6 +39,12 @@ Changes affecting backwards compatibility
you need that.
- The ``json.%`` operator is now overloaded for ``object``, ``ref object`` and
``openarray[T]``.
- The procs related to ``random`` number generation in ``math.nim`` have
been moved to its own ``random`` module and been reimplemented in pure
Nim.
- The path handling changed. The project directory is not added to the
search path automatically anymore. Add this line to your project's
config to get back the old behaviour: ``--path:"$projectdir"``.
Library Additions
@@ -64,11 +70,13 @@ Language Additions
- Nim now supports a ``.this`` pragma for more notational convenience.
- Nim now supports a different ``using`` statement for more convenience.
- Nim now supports ``partial`` object declarations to mitigate the problems
that arise when types are mutually dependent and yet should be kept in
different modules.
- ``include`` statements are not restricted to top level statements anymore.
..
- Nim now supports ``partial`` object declarations to mitigate the problems
that arise when types are mutually dependent and yet should be kept in
different modules.
2016-01-27 Nim in Action is now available!
==========================================

View File

@@ -39,7 +39,7 @@ srcdoc2: "impure/re;pure/typetraits"
srcdoc2: "pure/concurrency/threadpool.nim;pure/concurrency/cpuinfo.nim"
srcdoc: "system/threads.nim;system/channels.nim;js/dom"
srcdoc2: "pure/os;pure/strutils;pure/math;pure/matchers;pure/algorithm"
srcdoc2: "pure/stats;impure/nre;windows/winlean"
srcdoc2: "pure/stats;impure/nre;windows/winlean;pure/random"
srcdoc2: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib;pure/strscans"
srcdoc2: "pure/parseopt;pure/parseopt2;pure/hashes;pure/strtabs;pure/lexbase"
srcdoc2: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql"