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

@ -938,7 +938,7 @@ const
genericParamsPos* = 2 genericParamsPos* = 2
paramsPos* = 3 paramsPos* = 3
pragmasPos* = 4 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! bodyPos* = 6 # position of body; use rodread.getBody() instead!
resultPos* = 7 resultPos* = 7
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 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: else:
options.gProjectPath / path options.gProjectPath / path
try: try:
result = unixToNativePath(p % ["nimrod", getPrefixDir(), result = pathSubs(p, info.toFullPath().splitFile().dir)
"nim", getPrefixDir(),
"lib", libpath,
"home", removeTrailingDirSep(os.getHomeDir()),
"config", info.toFullPath().splitFile().dir,
"projectname", options.gProjectName,
"projectpath", options.gProjectPath])
except ValueError: except ValueError:
localError(info, "invalid path: " & p) localError(info, "invalid path: " & p)
result = p result = p
@ -322,6 +316,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
of "nonimblepath", "nobabelpath": of "nonimblepath", "nobabelpath":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
options.gNoNimblePath = true options.gNoNimblePath = true
options.lazyPaths.head = nil
options.lazyPaths.tail = nil
options.lazyPaths.counter = 0
of "excludepath": of "excludepath":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
let path = processPath(arg, 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 # The proc won't perform any checks that the path is actually valid
case n.kind case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit: 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: of nkIdent:
result = n.ident.s result = n.ident.s
of nkSym: of nkSym:

View file

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

View file

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

View file

@ -242,6 +242,21 @@ proc getNimcacheDir*: string =
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir / result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
genSubDir 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 = template newPackageCache(): expr =
newStringTable(when FileSystemCaseSensitive: newStringTable(when FileSystemCaseSensitive:
modeCaseInsensitive modeCaseInsensitive

View file

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

View file

@ -712,7 +712,11 @@ proc gproc(g: var TSrcGen, n: PNode) =
gpattern(g, n.sons[patternPos]) gpattern(g, n.sons[patternPos])
let oldCheckAnon = g.checkAnon let oldCheckAnon = g.checkAnon
g.checkAnon = true 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 g.checkAnon = oldCheckAnon
gsub(g, n.sons[paramsPos]) gsub(g, n.sons[paramsPos])
gsub(g, n.sons[pragmasPos]) gsub(g, n.sons[pragmasPos])

View file

@ -129,7 +129,11 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
add(result, ')') add(result, ')')
var candidates = "" var candidates = ""
for err in errors: 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") add(candidates, "\n")
if candidates != "": if candidates != "":
add(result, "\n" & msgKindToString(errButExpected) & "\n" & 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) pragma(c, result[namePos].sym, result[pragmasPos], validPragmas)
return 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 = proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
# XXX semProcAux should be good enough for this now, we will eventually # XXX semProcAux should be good enough for this now, we will eventually
# remove semLambda # remove semLambda
@ -947,8 +958,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
openScope(c) openScope(c)
var gp: PNode var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty: if n.sons[genericParamsPos].kind != nkEmpty:
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos]) gp = setGenericParamsMisc(c, n)
gp = n.sons[genericParamsPos]
else: else:
gp = newNodeI(nkGenericParams, n.info) gp = newNodeI(nkGenericParams, n.info)
@ -1170,8 +1180,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
openScope(c) openScope(c)
var gp: PNode var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty: if n.sons[genericParamsPos].kind != nkEmpty:
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos]) gp = setGenericParamsMisc(c, n)
gp = n.sons[genericParamsPos]
else: else:
gp = newNodeI(nkGenericParams, n.info) gp = newNodeI(nkGenericParams, n.info)
# process parameters: # process parameters:

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # 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 = proc readOutput(p: Process): string =
result = "" result = ""
@ -51,7 +51,9 @@ proc opGorge*(cmd, input, cache: string): string =
proc opSlurp*(file: string, info: TLineInfo, module: PSym): string = proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
try: try:
let filename = file.findFile var filename = parentDir(info.toFullPath) / file
if not fileExists(filename):
filename = file.findFile
result = readFile(filename) result = readFile(filename)
# we produce a fake include statement for every slurped filename, so that # we produce a fake include statement for every slurped filename, so that
# the module dependencies are accurate: # the module dependencies are accurate:

View file

@ -1887,8 +1887,8 @@ proc optimizeJumps(c: PCtx; start: int) =
else: discard else: discard
proc genProc(c: PCtx; s: PSym): int = proc genProc(c: PCtx; s: PSym): int =
let x = s.ast.sons[optimizedCodePos] var x = s.ast.sons[miscPos]
if x.kind == nkEmpty: if x.kind == nkEmpty or x[0].kind == nkEmpty:
#if s.name.s == "outterMacro" or s.name.s == "innerProc": #if s.name.s == "outterMacro" or s.name.s == "innerProc":
# echo "GENERATING CODE FOR ", s.name.s # echo "GENERATING CODE FOR ", s.name.s
let last = c.code.len-1 let last = c.code.len-1
@ -1899,7 +1899,11 @@ proc genProc(c: PCtx; s: PSym): int =
c.debug.setLen(last) c.debug.setLen(last)
#c.removeLastEof #c.removeLastEof
result = c.code.len+1 # skip the jump instruction 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 # thanks to the jmp we can add top level statements easily and also nest
# procs easily: # procs easily:
let body = s.getBody let body = s.getBody
@ -1934,4 +1938,4 @@ proc genProc(c: PCtx; s: PSym): int =
c.prc = oldPrc c.prc = oldPrc
else: else:
c.prc.maxSlots = s.offset 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 <mersenne.html>`_
Mersenne twister random number generator. Mersenne twister random number generator.
* `random <random.html>`_
Fast and tiny random number generator.
* `stats <stats.html>`_ * `stats <stats.html>`_
Statistical analysis Statistical analysis

View file

@ -155,4 +155,4 @@ Exception hierarchy
The exception tree is defined in the `system <system.html>`_ module: 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: The following keywords are reserved and cannot be used as identifiers:
.. code-block:: nim .. code-block:: nim
:file: keywords.txt :file: ../keywords.txt
Some keywords are unused; they are reserved for future developments of the Some keywords are unused; they are reserved for future developments of the
language. language.

View file

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

View file

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

View file

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

View file

@ -336,10 +336,11 @@ template `|`(a, b): expr = (if a.len > 0: a else: b)
proc tests(args: string) = proc tests(args: string) =
# we compile the tester with taintMode:on to have a basic # we compile the tester with taintMode:on to have a basic
# taint mode test :-) # 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 # 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! # 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 tester = quoteShell(getCurrentDir() / "tests/testament/tester".exe)
let success = tryExec tester & " " & (args|"all") let success = tryExec tester & " " & (args|"all")
if not existsEnv("TRAVIS") and not existsEnv("APPVEYOR"): 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 ## This module contains the interface to the compiler's abstract syntax
## tree (`AST`:idx:). Macros operate on this tree. ## tree (`AST`:idx:). Macros operate on this tree.
## .. include:: ../doc/astspec.txt ## .. include:: ../../doc/astspec.txt
type type
NimNodeKind* = enum NimNodeKind* = enum

View file

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

View file

@ -323,6 +323,11 @@ proc newSharedState(options: RstParseOptions,
result.msgHandler = if not isNil(msgHandler): msgHandler else: defaultMsgHandler result.msgHandler = if not isNil(msgHandler): msgHandler else: defaultMsgHandler
result.findFile = if not isNil(findFile): findFile else: defaultFindFile 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) = proc rstMessage(p: RstParser, msgKind: MsgKind, arg: string) =
p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line, p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line,
p.col + p.tok[p.idx].col, msgKind, arg) p.col + p.tok[p.idx].col, msgKind, arg)
@ -1500,7 +1505,7 @@ proc dirInclude(p: var RstParser): PRstNode =
result = nil result = nil
var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil) var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil)
var filename = strip(addNodes(n.sons[0])) var filename = strip(addNodes(n.sons[0]))
var path = p.s.findFile(filename) var path = p.findRelativeFile(filename)
if path == "": if path == "":
rstMessage(p, meCannotOpenFile, filename) rstMessage(p, meCannotOpenFile, filename)
else: else:
@ -1511,7 +1516,7 @@ proc dirInclude(p: var RstParser): PRstNode =
else: else:
var q: RstParser var q: RstParser
initParser(q, p.s) initParser(q, p.s)
q.filename = filename q.filename = path
q.col += getTokens(readFile(path), false, q.tok) q.col += getTokens(readFile(path), false, q.tok)
# workaround a GCC bug; more like the interior pointer bug? # workaround a GCC bug; more like the interior pointer bug?
#if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0: #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) result = parseDirective(p, {hasArg, hasOptions}, parseLiteralBlock)
var filename = strip(getFieldValue(result, "file")) var filename = strip(getFieldValue(result, "file"))
if filename != "": if filename != "":
var path = p.s.findFile(filename) var path = p.findRelativeFile(filename)
if path == "": rstMessage(p, meCannotOpenFile, filename) if path == "": rstMessage(p, meCannotOpenFile, filename)
var n = newRstNode(rnLiteralBlock) var n = newRstNode(rnLiteralBlock)
add(n, newRstNode(rnLeaf, readFile(path))) add(n, newRstNode(rnLeaf, readFile(path)))
@ -1590,7 +1595,7 @@ proc dirRawAux(p: var RstParser, result: var PRstNode, kind: RstNodeKind,
contentParser: SectionParser) = contentParser: SectionParser) =
var filename = getFieldValue(result, "file") var filename = getFieldValue(result, "file")
if filename.len > 0: if filename.len > 0:
var path = p.s.findFile(filename) var path = p.findRelativeFile(filename)
if path.len == 0: if path.len == 0:
rstMessage(p, meCannotOpenFile, filename) rstMessage(p, meCannotOpenFile, filename)
else: else:

View file

@ -219,20 +219,20 @@ proc processClient(client: AsyncSocket, address: string,
else: else:
await client.sendStatus("417 Expectation Failed") await client.sendStatus("417 Expectation Failed")
# Read the body # Read the body
# - Check for Content-length header # - Check for Content-length header
if request.headers.hasKey("Content-Length"): if request.headers.hasKey("Content-Length"):
var contentLength = 0 var contentLength = 0
if parseInt(request.headers.getOrDefault("Content-Length"), if parseInt(request.headers.getOrDefault("Content-Length"),
contentLength) == 0: contentLength) == 0:
await request.respond(Http400, "Bad Request. Invalid Content-Length.") 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 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 case request.reqMethod
of "get", "post", "head", "put", "delete", "trace", "options", 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[1][0] = true
## seq2D[0][1] = true ## seq2D[0][1] = true
## ##
## import math ## import random
## var seqRand = newSeqWith(20, random(10)) ## var seqRand = newSeqWith(20, random(10))
## echo seqRand ## echo seqRand
var result {.gensym.} = newSeq[type(init)](len) var result {.gensym.} = newSeq[type(init)](len)

View file

@ -79,6 +79,8 @@ proc advice*(s: var ThreadPoolState): ThreadPoolAdvice =
inc s.calls inc s.calls
when not defined(testing) and isMainModule: when not defined(testing) and isMainModule:
import random
proc busyLoop() = proc busyLoop() =
while true: while true:
discard random(80) discard random(80)

View file

@ -29,21 +29,17 @@ proc createProcType(p, b: NimNode): NimNode {.compileTime.} =
of nnkExprColonExpr: of nnkExprColonExpr:
identDefs.add ident[0] identDefs.add ident[0]
identDefs.add ident[1] identDefs.add ident[1]
of nnkIdent: else:
identDefs.add newIdentNode("i" & $i) identDefs.add newIdentNode("i" & $i)
identDefs.add(ident) identDefs.add(ident)
else:
error("Incorrect type list in proc type declaration.")
identDefs.add newEmptyNode() identDefs.add newEmptyNode()
formalParams.add identDefs formalParams.add identDefs
of nnkIdent: else:
var identDefs = newNimNode(nnkIdentDefs) var identDefs = newNimNode(nnkIdentDefs)
identDefs.add newIdentNode("i0") identDefs.add newIdentNode("i0")
identDefs.add(p) identDefs.add(p)
identDefs.add newEmptyNode() identDefs.add newEmptyNode()
formalParams.add identDefs formalParams.add identDefs
else:
error("Incorrect type list in proc type declaration.")
result.add formalParams result.add formalParams
result.add newEmptyNode() result.add newEmptyNode()

View file

@ -79,7 +79,8 @@
## constructor should be used for this purpose. However, ## constructor should be used for this purpose. However,
## currently only basic authentication is supported. ## 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 asyncnet, asyncdispatch
import nativesockets import nativesockets

View file

@ -39,8 +39,6 @@ proc fac*(n: int): int {.noSideEffect.} =
when defined(Posix) and not defined(haiku): when defined(Posix) and not defined(haiku):
{.passl: "-lm".} {.passl: "-lm".}
when not defined(js) and not defined(nimscript):
import times
const const
PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number) 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. ## If `x` is empty, 0 is returned.
for i in items(x): result = result + i 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.} {.push noSideEffect.}
when not defined(JS): when not defined(JS):
proc sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".} 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>".} proc tgamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".}
## The gamma function ## 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: float32): float32 {.importc: "truncf", header: "<math.h>".}
proc trunc*(x: float64): float64 {.importc: "trunc", header: "<math.h>".} proc trunc*(x: float64): float64 {.importc: "trunc", header: "<math.h>".}
## Truncates `x` to the decimal point ## Truncates `x` to the decimal point
@ -319,17 +242,10 @@ when not defined(JS):
## echo fmod(-2.5, 0.3) ## -0.1 ## echo fmod(-2.5, 0.3) ## -0.1
else: else:
proc mathrandom(): float {.importc: "Math.random", nodecl.}
proc floor*(x: float32): float32 {.importc: "Math.floor", nodecl.} proc floor*(x: float32): float32 {.importc: "Math.floor", nodecl.}
proc floor*(x: float64): float64 {.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: float32): float32 {.importc: "Math.ceil", nodecl.}
proc ceil*(x: float64): float64 {.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: float32): float32 {.importc: "Math.sqrt", nodecl.}
proc sqrt*(x: float64): float64 {.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 ## echo (4.0 mod -3.1) # -2.2
result = if y == 0.0: x else: x - y * (x/y).floor 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.}
{.pop.} {.pop.}
@ -440,24 +348,6 @@ proc lcm*[T](x, y: T): T =
x div gcd(x, y) * y x div gcd(x, y) * y
when isMainModule and not defined(JS): 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 # Check for no side effect annotation
proc mySqrt(num: float): float {.noSideEffect.} = proc mySqrt(num: float): float {.noSideEffect.} =
return sqrt(num) 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) var valuei = cint(if value: 1 else: 0)
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei) 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 = proc makeUnixAddr(path: string): Sockaddr_un =
result.sun_family = AF_UNIX.toInt result.sun_family = AF_UNIX.toInt
if path.len >= Sockaddr_un_path_length: if path.len >= Sockaddr_un_path_length:
raise newException(ValueError, "socket path too long") raise newException(ValueError, "socket path too long")
copyMem(addr result.sun_path, path.cstring, path.len + 1) copyMem(addr result.sun_path, path.cstring, path.len + 1)
when defined(posix):
proc connectUnix*(socket: Socket, path: string) = proc connectUnix*(socket: Socket, path: string) =
## Connects to Unix socket on `path`. ## Connects to Unix socket on `path`.
## This only works on Unix-style systems: Mac OS X, BSD and Linux ## This only works on Unix-style systems: Mac OS X, BSD and Linux
var socketAddr = makeUnixAddr(path) when not defined(nimdoc):
if socket.fd.connect(cast[ptr SockAddr](addr socketAddr), var socketAddr = makeUnixAddr(path)
sizeof(socketAddr).Socklen) != 0'i32: if socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
raiseOSError(osLastError()) sizeof(socketAddr).Socklen) != 0'i32:
raiseOSError(osLastError())
proc bindUnix*(socket: Socket, path: string) = proc bindUnix*(socket: Socket, path: string) =
## Binds Unix socket to `path`. ## Binds Unix socket to `path`.
## This only works on Unix-style systems: Mac OS X, BSD and Linux ## This only works on Unix-style systems: Mac OS X, BSD and Linux
var socketAddr = makeUnixAddr(path) when not defined(nimdoc):
if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr), var socketAddr = makeUnixAddr(path)
sizeof(socketAddr).Socklen) != 0'i32: if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
raiseOSError(osLastError()) sizeof(socketAddr).Socklen) != 0'i32:
raiseOSError(osLastError())
when defined(ssl): when defined(ssl):
proc handshake*(socket: Socket): bool proc handshake*(socket: Socket): bool
@ -1399,7 +1402,7 @@ proc connect*(socket: Socket, address: string, port = Port(0),
if selectWrite(s, timeout) != 1: if selectWrite(s, timeout) != 1:
raise newException(TimeoutError, "Call to 'connect' timed out.") raise newException(TimeoutError, "Call to 'connect' timed out.")
else: else:
when defineSsl: when defineSsl and not defined(nimdoc):
if socket.isSSL: if socket.isSSL:
socket.fd.setBlocking(true) socket.fd.setBlocking(true)
{.warning[Deprecated]: off.} {.warning[Deprecated]: off.}

View file

@ -15,21 +15,21 @@
## This is an example of how a configuration file may look like: ## This is an example of how a configuration file may look like:
## ##
## .. include:: doc/mytest.cfg ## .. include:: ../../doc/mytest.cfg
## :literal: ## :literal:
## The file ``examples/parsecfgex.nim`` demonstrates how to use the ## The file ``examples/parsecfgex.nim`` demonstrates how to use the
## configuration file parser: ## configuration file parser:
## ##
## .. code-block:: nim ## .. code-block:: nim
## :file: examples/parsecfgex.nim ## :file: ../../examples/parsecfgex.nim
## ##
## Examples ## Examples
## -------- ## --------
## ##
## This is an example of a configuration file. ## This is an example of a configuration file.
## ##
## .. include:: config.ini ## ::
## ##
## charset = "utf-8" ## charset = "utf-8"
## [Package] ## [Package]
## name = "hello" ## name = "hello"
@ -38,11 +38,11 @@
## name = "lihf8515" ## name = "lihf8515"
## qq = "10214028" ## qq = "10214028"
## email = "lihaifeng@wxm.com" ## email = "lihaifeng@wxm.com"
## ##
## Creating a configuration file. ## Creating a configuration file.
## ============================== ## ==============================
## .. code-block:: nim ## .. code-block:: nim
## ##
## import parsecfg ## import parsecfg
## var dict=newConfig() ## var dict=newConfig()
## dict.setSectionKey("","charset","utf-8") ## dict.setSectionKey("","charset","utf-8")
@ -52,7 +52,7 @@
## dict.setSectionKey("Author","qq","10214028") ## dict.setSectionKey("Author","qq","10214028")
## dict.setSectionKey("Author","email","lihaifeng@wxm.com") ## dict.setSectionKey("Author","email","lihaifeng@wxm.com")
## dict.writeConfig("config.ini") ## dict.writeConfig("config.ini")
## ##
## Reading a configuration file. ## Reading a configuration file.
## ============================= ## =============================
## .. code-block:: nim ## .. code-block:: nim
@ -66,11 +66,11 @@
## var qq = dict.getSectionValue("Author","qq") ## var qq = dict.getSectionValue("Author","qq")
## var email = dict.getSectionValue("Author","email") ## var email = dict.getSectionValue("Author","email")
## echo pname & "\n" & name & "\n" & qq & "\n" & email ## echo pname & "\n" & name & "\n" & qq & "\n" & email
## ##
## Modifying a configuration file. ## Modifying a configuration file.
## =============================== ## ===============================
## .. code-block:: nim ## .. code-block:: nim
## ##
## import parsecfg ## import parsecfg
## var dict = loadConfig("config.ini") ## var dict = loadConfig("config.ini")
## dict.setSectionKey("Author","name","lhf") ## dict.setSectionKey("Author","name","lhf")
@ -79,7 +79,7 @@
## Deleting a section key in a configuration file. ## Deleting a section key in a configuration file.
## =============================================== ## ===============================================
## .. code-block:: nim ## .. code-block:: nim
## ##
## import parsecfg ## import parsecfg
## var dict = loadConfig("config.ini") ## var dict = loadConfig("config.ini")
## dict.delSectionKey("Author","email") ## dict.delSectionKey("Author","email")
@ -434,7 +434,7 @@ proc loadConfig*(filename: string): Config =
## Load the specified configuration file into a new Config instance. ## Load the specified configuration file into a new Config instance.
var dict = newOrderedTable[string, OrderedTableRef[string, string]]() var dict = newOrderedTable[string, OrderedTableRef[string, string]]()
var curSection = "" ## Current section, 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 ## which means that the current section is a common
var p: CfgParser var p: CfgParser
var fileStream = newFileStream(filename, fmRead) var fileStream = newFileStream(filename, fmRead)

View file

@ -34,7 +34,7 @@
## document. ## document.
## ##
## .. code-block:: nim ## .. code-block:: nim
## :file: examples/htmltitle.nim ## :file: ../../examples/htmltitle.nim
## ##
## ##
## Example 2: Retrieve all HTML links ## Example 2: Retrieve all HTML links
@ -45,7 +45,7 @@
## an HTML document contains. ## an HTML document contains.
## ##
## .. code-block:: nim ## .. code-block:: nim
## :file: examples/htmlrefs.nim ## :file: ../../examples/htmlrefs.nim
## ##
import import

View file

@ -12,7 +12,7 @@
## Matching performance is hopefully competitive with optimized regular ## Matching performance is hopefully competitive with optimized regular
## expression engines. ## expression engines.
## ##
## .. include:: ../doc/pegdocs.txt ## .. include:: ../../doc/pegdocs.txt
## ##
include "system/inclrtl" 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:). ## 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 {.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) {. proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {.
importc: "gettimeofday", header: "<sys/time.h>".} importc: "gettimeofday", header: "<sys/time.h>".}
var when not defined(freebsd) and not defined(netbsd) and not defined(openbsd):
timezone {.importc, header: "<time.h>".}: int var timezone {.importc, header: "<time.h>".}: int
var
tzname {.importc, header: "<time.h>" .}: array[0..1, cstring] tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
# we also need tzset() to make sure that tzname is initialized # we also need tzset() to make sure that tzname is initialized
proc tzset() {.importc, header: "<time.h>".} proc tzset() {.importc, header: "<time.h>".}
@ -416,18 +417,32 @@ when not defined(JS):
when not defined(JS): when not defined(JS):
# C wrapper: # 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 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 TimeInfoPtr = ptr StructTM
Clock {.importc: "clock_t".} = distinct int Clock {.importc: "clock_t".} = distinct int
@ -457,24 +472,47 @@ when not defined(JS):
const const
weekDays: array [0..6, WeekDay] = [ weekDays: array [0..6, WeekDay] = [
dSun, dMon, dTue, dWed, dThu, dFri, dSat] dSun, dMon, dTue, dWed, dThu, dFri, dSat]
TimeInfo(second: int(tm.second), when defined(freebsd) or defined(netbsd) or defined(openbsd):
minute: int(tm.minute), TimeInfo(second: int(tm.second),
hour: int(tm.hour), minute: int(tm.minute),
monthday: int(tm.monthday), hour: int(tm.hour),
month: Month(tm.month), monthday: int(tm.monthday),
year: tm.year + 1900'i32, month: Month(tm.month),
weekday: weekDays[int(tm.weekday)], year: tm.year + 1900'i32,
yearday: int(tm.yearday), weekday: weekDays[int(tm.weekday)],
isDST: tm.isdst > 0, yearday: int(tm.yearday),
tzname: if local: isDST: tm.isdst > 0,
if tm.isdst > 0: tzname: if local:
getTzname().DST if tm.isdst > 0:
getTzname().DST
else:
getTzname().nonDST
else: else:
getTzname().nonDST "UTC",
else: # BSD stores in `gmtoff` offset east of UTC in seconds,
"UTC", # but posix systems using west of UTC in seconds
timezone: if local: getTimezone() else: 0 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 = proc timeInfoToTM(t: TimeInfo): StructTM =
const const
@ -564,7 +602,14 @@ when not defined(JS):
return ($tzname[0], $tzname[1]) return ($tzname[0], $tzname[1])
proc getTimezone(): int = 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) 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 ## .. code-block:: nim
## ##
## import math ## import math, random
## proc defectiveRobot() = ## proc defectiveRobot() =
## randomize() ## randomize()
## case random(1..4) ## case random(1..4)

View file

@ -2514,7 +2514,7 @@ template newException*(exceptn: typedesc, message: string): expr =
e e
when hostOS == "standalone": when hostOS == "standalone":
include panicoverride include "$projectpath/panicoverride"
when not declared(sysFatal): when not declared(sysFatal):
when hostOS == "standalone": when hostOS == "standalone":

View file

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

View file

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

View file

@ -1,5 +1,5 @@
import nake import nake
import httpclient, zip/zipfiles, times, math, sequtils import httpclient, zip/zipfiles, times, random, sequtils
nakeImports nakeImports
randomize() randomize()
@ -145,7 +145,7 @@ task "download", "download game assets":
echo "Extracted the libs dir. Copy the ones you need to this dir." echo "Extracted the libs dir. Copy the ones you need to this dir."
task "zip-lib", "zip up the libs dir": task "zip-lib", "zip up the libs dir":
var z: TZipArchive var z: ZipArchive
if not z.open("libs-" & getDateStr() & ".zip", fmReadWrite): if not z.open("libs-" & getDateStr() & ".zip", fmReadWrite):
quit "Could not open zip" quit "Could not open zip"
for file in walkDirRec("libs", {pcFile, pcDir}): 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 # this file only exists to mark 'main.nim' as the main file
--path:"$projectpath"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
News News
==== ====
2016-XX-XX Version 0.13.1 released 2016-XX-XX Version 0.14.0 released
================================== ==================================
Changes affecting backwards compatibility Changes affecting backwards compatibility
@ -39,6 +39,12 @@ Changes affecting backwards compatibility
you need that. you need that.
- The ``json.%`` operator is now overloaded for ``object``, ``ref object`` and - The ``json.%`` operator is now overloaded for ``object``, ``ref object`` and
``openarray[T]``. ``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 Library Additions
@ -64,11 +70,13 @@ Language Additions
- Nim now supports a ``.this`` pragma for more notational convenience. - Nim now supports a ``.this`` pragma for more notational convenience.
- Nim now supports a different ``using`` statement for more 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. - ``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! 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" srcdoc2: "pure/concurrency/threadpool.nim;pure/concurrency/cpuinfo.nim"
srcdoc: "system/threads.nim;system/channels.nim;js/dom" srcdoc: "system/threads.nim;system/channels.nim;js/dom"
srcdoc2: "pure/os;pure/strutils;pure/math;pure/matchers;pure/algorithm" 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/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib;pure/strscans"
srcdoc2: "pure/parseopt;pure/parseopt2;pure/hashes;pure/strtabs;pure/lexbase" srcdoc2: "pure/parseopt;pure/parseopt2;pure/hashes;pure/strtabs;pure/lexbase"
srcdoc2: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql" srcdoc2: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql"