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

This commit is contained in:
Andreas Rumpf
2016-02-06 15:29:25 +01:00
50 changed files with 224 additions and 202 deletions

View File

@@ -137,7 +137,7 @@ proc sameValue*(a, b: PNode): bool =
of nkStrLit..nkTripleStrLit:
if b.kind in {nkStrLit..nkTripleStrLit}: result = a.strVal == b.strVal
else:
# don't raise an internal error for 'nimrod check':
# don't raise an internal error for 'nim check':
#InternalError(a.info, "SameValue")
discard
@@ -152,7 +152,7 @@ proc leValue*(a, b: PNode): bool =
of nkStrLit..nkTripleStrLit:
if b.kind in {nkStrLit..nkTripleStrLit}: result = a.strVal <= b.strVal
else:
# don't raise an internal error for 'nimrod check':
# don't raise an internal error for 'nim check':
#InternalError(a.info, "leValue")
discard

View File

@@ -11,7 +11,7 @@
import strutils, db_sqlite, md5
var db: TDbConn
var db: DbConn
# We *hash* the relevant information into 128 bit hashes. This should be good
# enough to prevent any collisions.
@@ -33,7 +33,7 @@ type
const
cb64 = [
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
"O", "P", "Q", "R", "S", "T" "U", "V", "W", "X", "Y", "Z",
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",

View File

@@ -24,7 +24,7 @@ proc accessThreadLocalVar(p: BProc, s: PSym) =
ropecg(p.module, "\tNimTV = (NimThreadVars*) #GetThreadLocalVars();$n"))
var
nimtv: Rope # nimrod thread vars; the struct body
nimtv: Rope # Nim thread vars; the struct body
nimtvDeps: seq[PType] = @[] # type deps: every module needs whole struct
nimtvDeclared = initIntSet() # so that every var/field exists only once
# in the struct

View File

@@ -47,7 +47,7 @@ proc mangleName(s: PSym): Rope =
# I need to study where these come from.
#
# about sfShadowed:
# consider the following nimrod code:
# consider the following Nim code:
# var x = 10
# block:
# var x = something(x)
@@ -64,7 +64,7 @@ proc mangleName(s: PSym): Rope =
# use that in the inner scope.
#
# about isCKeyword:
# nimrod variable names can be C keywords.
# Nim variable names can be C keywords.
# We need to avoid such names in the generated code.
# XXX: Study whether mangleName is called just once per variable.
# Otherwise, there might be better place to do this.

View File

@@ -44,7 +44,7 @@ proc toGid(f: string): string =
# we used to use ``f.addFileExt("gid")`` (aka ``$project.gid``), but this
# will cause strange bugs if multiple projects are in the same folder, so
# we simply use a project independent name:
result = options.completeGeneratedFilePath("nimrod.gid")
result = options.completeGeneratedFilePath("nim.gid")
proc saveMaxIds*(project: string) =
var f = open(project.toGid, fmWrite)

View File

@@ -1138,6 +1138,18 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v
createRecordVarAux(p, t.n, excludedFieldIDs, output)
t = t.sons[0]
proc arrayTypeForElemType(typ: PType): string =
case typ.kind
of tyInt, tyInt32: "Int32Array"
of tyInt16: "Int16Array"
of tyInt8: "Int8Array"
of tyUint, tyUint32: "Uint32Array"
of tyUint16: "Uint16Array"
of tyUint8: "Uint8Array"
of tyFloat32: "Float32Array"
of tyFloat64, tyFloat: "Float64Array"
else: nil
proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
var t = skipTypes(typ, abstractInst)
case t.kind
@@ -1152,9 +1164,12 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
of tyBool:
result = putToSeq("false", indirect)
of tyArray, tyArrayConstr:
var length = int(lengthOrd(t))
var e = elemType(t)
if length > 32:
let length = int(lengthOrd(t))
let e = elemType(t)
let jsTyp = arrayTypeForElemType(e)
if not jsTyp.isNil:
result = "new $1($2)" % [rope(jsTyp), rope(length)]
elif length > 32:
useMagic(p, "arrayConstr")
# XXX: arrayConstr depends on nimCopy. This line shouldn't be necessary.
useMagic(p, "nimCopy")
@@ -1766,7 +1781,15 @@ proc genHeader(): Rope =
"/* (c) 2015 Andreas Rumpf */$n$n" &
"var framePtr = null;$n" &
"var excHandler = 0;$n" &
"var lastJSError = null;$n") %
"var lastJSError = null;$n" &
"if (typeof Int8Array === 'undefined') Int8Array = Array;$n" &
"if (typeof Int16Array === 'undefined') Int16Array = Array;$n" &
"if (typeof Int32Array === 'undefined') Int32Array = Array;$n" &
"if (typeof Uint8Array === 'undefined') Uint8Array = Array;$n" &
"if (typeof Uint16Array === 'undefined') Uint16Array = Array;$n" &
"if (typeof Uint32Array === 'undefined') Uint32Array = Array;$n" &
"if (typeof Float32Array === 'undefined') Float32Array = Array;$n" &
"if (typeof Float64Array === 'undefined') Float64Array = Array;$n") %
[rope(VersionAsString)]
proc genModule(p: PProc, n: PNode) =

View File

@@ -147,8 +147,8 @@ var
gDllOverrides = newStringTable(modeCaseInsensitive)
gPrefixDir* = "" # Overrides the default prefix dir in getPrefixDir proc.
libpath* = ""
gProjectName* = "" # holds a name like 'nimrod'
gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
gProjectName* = "" # holds a name like 'nim'
gProjectPath* = "" # holds a path like /home/alice/projects/nim/compiler/
gProjectFull* = "" # projectPath/projectName
gProjectIsStdin* = false # whether we're compiling from stdin
gProjectMainIdx*: int32 # the canonical path id of the main module

View File

@@ -10,7 +10,7 @@
# This module contains data about the different processors
# and operating systems.
# Note: Unfortunately if an OS or CPU is listed here this does not mean that
# Nimrod has been tested on this platform or that the RTL has been ported.
# Nim has been tested on this platform or that the RTL has been ported.
# Feel free to test for your excentric platform!
import

View File

@@ -130,7 +130,7 @@ that ``spawn`` takes is restricted:
programmer to be careful.
* ``ref`` parameters are deeply copied which is a subtle semantic change and
can cause performance problems but ensures memory safety. This deep copy
is performed via ``system.deepCopy`` and so can be overriden.
is performed via ``system.deepCopy`` and so can be overridden.
* For *safe* data exchange between ``f`` and the caller a global ``TChannel``
needs to be used. However, since spawn can return a result, often no further
communication is required.

View File

@@ -3,7 +3,7 @@
import backend, parseopt, strutils
const
USAGE = """nimcalculator - Nimrod cross platform calculator
USAGE = """nimcalculator - Nim cross platform calculator
(beta version, only integer addition is supported!)
Usage:

View File

@@ -1,6 +1,6 @@
# Backend for a simple todo program with sqlite persistence.
#
# Most procs dealing with a TDbConn object may raise an EDb exception.
# Most procs dealing with a DbConn object may raise an EDb exception.
import db_sqlite, parseutils, strutils, times
@@ -42,7 +42,7 @@ proc initDefaults*(params: var TPagedParams) =
params.showChecked = false
proc openDatabase*(path: string): TDbConn =
proc openDatabase*(path: string): DbConn =
## Creates or opens the sqlite3 database.
##
## Pass the path to the sqlite database, if the database doesn't exist it
@@ -86,7 +86,7 @@ proc getModificationDate*(todo: TTodo): Time =
return todo.modificationDate
proc update*(todo: var TTodo; conn: TDbConn): bool =
proc update*(todo: var TTodo; conn: DbConn): bool =
## Checks the database for the object and refreshes its variables.
##
## Use this method if you (or another entity) have modified the database and
@@ -112,7 +112,7 @@ proc update*(todo: var TTodo; conn: TDbConn): bool =
echo("Something went wrong selecting for id " & $todo.id)
proc save*(todo: var TTodo; conn: TDbConn): bool =
proc save*(todo: var TTodo; conn: DbConn): bool =
## Saves the current state of text, priority and isDone to the database.
##
## Returns true if the database object was updated (in which case the
@@ -135,7 +135,7 @@ proc save*(todo: var TTodo; conn: TDbConn): bool =
# - Procs dealing directly with the database
#
proc addTodo*(conn: TDbConn; priority: int; text: string): TTodo =
proc addTodo*(conn: DbConn; priority: int; text: string): TTodo =
## Inserts a new todo into the database.
##
## Returns the generated todo object. If there is an error EDb will be raised.
@@ -149,7 +149,7 @@ proc addTodo*(conn: TDbConn; priority: int; text: string): TTodo =
result = initFromDB(todoId, text, priority, false, currentDate)
proc deleteTodo*(conn: TDbConn; todoId: int64): int64 {.discardable.} =
proc deleteTodo*(conn: DbConn; todoId: int64): int64 {.discardable.} =
## Deletes the specified todo identifier.
##
## Returns the number of rows which were affected (1 or 0)
@@ -157,7 +157,7 @@ proc deleteTodo*(conn: TDbConn; todoId: int64): int64 {.discardable.} =
result = conn.execAffectedRows(query, $todoId)
proc getNumEntries*(conn: TDbConn): int =
proc getNumEntries*(conn: DbConn): int =
## Returns the number of entries in the Todos table.
##
## If the function succeeds, returns the zero or positive value, if something
@@ -171,7 +171,7 @@ proc getNumEntries*(conn: TDbConn): int =
result = -1
proc getPagedTodos*(conn: TDbConn; params: TPagedParams;
proc getPagedTodos*(conn: DbConn; params: TPagedParams;
page = 0'i64): seq[TTodo] =
## Returns the todo entries for a specific page.
##
@@ -210,7 +210,7 @@ proc getPagedTodos*(conn: TDbConn; params: TPagedParams;
row[3].parseBool, Time(row[4].parseInt)))
proc getTodo*(conn: TDbConn; todoId: int64): ref TTodo =
proc getTodo*(conn: DbConn; todoId: int64): ref TTodo =
## Returns a reference to a TTodo or nil if the todo could not be found.
var tempTodo: TTodo
tempTodo.id = todoId

View File

@@ -3,7 +3,7 @@
import backend, db_sqlite, strutils, times
proc showPagedResults(conn: TDbConn; params: TPagedParams) =
proc showPagedResults(conn: DbConn; params: TPagedParams) =
## Shows the contents of the database in pages of specified size.
##
## Hmm... I guess this is more of a debug proc which should be moved outside,

View File

@@ -3,7 +3,7 @@
import backend, db_sqlite, os, parseopt, parseutils, strutils, times
const
USAGE = """nimtodo - Nimrod cross platform todo manager
USAGE = """nimtodo - Nim cross platform todo manager
Usage:
nimtodo [command] [list options]
@@ -191,11 +191,11 @@ proc parseCmdLine(): TParamConfig =
abort("Used list options, but didn't specify the list command.", 10)
proc generateDatabaseRows(conn: TDbConn) =
proc generateDatabaseRows(conn: DbConn) =
## Adds some rows to the database ignoring errors.
discard conn.addTodo(1, "Watch another random youtube video")
discard conn.addTodo(2, "Train some starcraft moves for the league")
discard conn.addTodo(3, "Spread the word about Nimrod")
discard conn.addTodo(3, "Spread the word about Nim")
discard conn.addTodo(4, "Give fruit superavit to neighbours")
var todo = conn.addTodo(4, "Send tax form through snail mail")
todo.isDone = true
@@ -209,7 +209,7 @@ proc generateDatabaseRows(conn: TDbConn) =
echo("Generated some entries, they were added to your database.")
proc listDatabaseContents(conn: TDbConn; listParams: TPagedParams) =
proc listDatabaseContents(conn: DbConn; listParams: TPagedParams) =
## Dumps the database contents formatted to the standard output.
##
## Pass the list/filter parameters parsed from the commandline.
@@ -239,7 +239,7 @@ proc listDatabaseContents(conn: TDbConn; listParams: TPagedParams) =
todo.text])
proc deleteOneTodo(conn: TDbConn; todoId: int64) =
proc deleteOneTodo(conn: DbConn; todoId: int64) =
## Deletes a single todo entry from the database.
let numDeleted = conn.deleteTodo(todoId)
if numDeleted > 0:
@@ -248,7 +248,7 @@ proc deleteOneTodo(conn: TDbConn; todoId: int64) =
quit("Couldn't delete todo id " & $todoId, 11)
proc deleteAllTodos(conn: TDbConn) =
proc deleteAllTodos(conn: DbConn) =
## Deletes all the contents from the database.
##
## Note that it would be more optimal to issue a direct DELETE sql statement
@@ -273,7 +273,7 @@ proc deleteAllTodos(conn: TDbConn) =
echo("Deleted $1 todo entries from database." % $counter)
proc setTodoCheck(conn: TDbConn; todoId: int64; value: bool) =
proc setTodoCheck(conn: DbConn; todoId: int64; value: bool) =
## Changes the check state of a todo entry to the specified value.
let
newState = if value: "checked" else: "unchecked"
@@ -293,7 +293,7 @@ proc setTodoCheck(conn: TDbConn; todoId: int64; value: bool) =
quit("Error updating todo id $1 to $2." % [$todoId, newState])
proc addTodo(conn: TDbConn; priority: int; tokens: seq[string]) =
proc addTodo(conn: DbConn; priority: int; tokens: seq[string]) =
## Adds to the database a todo with the specified priority.
##
## The tokens are joined as a single string using the space character. The

View File

@@ -28,6 +28,6 @@ html mainPage:
title "now look at this"
body:
ul:
li "Nimrod is quite capable"
li "Nim is quite capable"
echo mainPage()

View File

@@ -40,7 +40,7 @@ type
Actor[In, Out] = object{.pure, final.}
i: Channel[Task[In, Out]]
t: TThread[ptr Actor[In, Out]]
t: Thread[ptr Actor[In, Out]]
PActor*[In, Out] = ptr Actor[In, Out] ## an actor
{.deprecated: [TTask: Task, TActor: Actor].}

View File

@@ -39,7 +39,6 @@ when hostOS == "solaris":
import os, parseutils
from times import epochTime
import unsigned
when defined(ssl):
import openssl

View File

@@ -10,7 +10,6 @@
from pcre import nil
import nre.private.util
import tables
import unsigned
from strutils import toLower, `%`
from math import ceil
import options

View File

@@ -1518,7 +1518,7 @@ proc dirInclude(p: var RstParser): PRstNode =
# InternalError("Too many binary zeros in include file")
result = parseDoc(q)
proc dirCodeBlock(p: var RstParser, nimrodExtension = false): PRstNode =
proc dirCodeBlock(p: var RstParser, nimExtension = false): PRstNode =
## Parses a code block.
##
## Code blocks are rnDirective trees with a `kind` of rnCodeBlock. See the
@@ -1526,8 +1526,8 @@ proc dirCodeBlock(p: var RstParser, nimrodExtension = false): PRstNode =
##
## Code blocks can come in two forms, the standard `code directive
## <http://docutils.sourceforge.net/docs/ref/rst/directives.html#code>`_ and
## the nimrod extension ``.. code-block::``. If the block is an extension, we
## want the default language syntax highlighting to be Nimrod, so we create a
## the nim extension ``.. code-block::``. If the block is an extension, we
## want the default language syntax highlighting to be Nim, so we create a
## fake internal field to comminicate with the generator. The field is named
## ``default-language``, which is unlikely to collide with a field specified
## by any random rst input file.
@@ -1545,16 +1545,16 @@ proc dirCodeBlock(p: var RstParser, nimrodExtension = false): PRstNode =
result.sons[2] = n
# Extend the field block if we are using our custom extension.
if nimrodExtension:
if nimExtension:
# Create a field block if the input block didn't have any.
if result.sons[1].isNil: result.sons[1] = newRstNode(rnFieldList)
assert result.sons[1].kind == rnFieldList
# Hook the extra field and specify the Nimrod language as value.
# Hook the extra field and specify the Nim language as value.
var extraNode = newRstNode(rnField)
extraNode.add(newRstNode(rnFieldName))
extraNode.add(newRstNode(rnFieldBody))
extraNode.sons[0].add(newRstNode(rnLeaf, "default-language"))
extraNode.sons[1].add(newRstNode(rnLeaf, "Nimrod"))
extraNode.sons[1].add(newRstNode(rnLeaf, "Nim"))
result.sons[1].add(extraNode)
result.kind = rnCodeBlock
@@ -1641,7 +1641,7 @@ proc parseDotDot(p: var RstParser): PRstNode =
else:
rstMessage(p, meInvalidDirective, d)
of dkCode: result = dirCodeBlock(p)
of dkCodeBlock: result = dirCodeBlock(p, nimrodExtension = true)
of dkCodeBlock: result = dirCodeBlock(p, nimExtension = true)
of dkIndex: result = dirIndex(p)
else: rstMessage(p, meInvalidDirective, d)
popInd(p)

View File

@@ -757,10 +757,15 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
template valid(s): expr =
s.len > 0 and allCharsInSet(s, {'.','/',':','%','_','\\','\128'..'\xFF'} +
Digits + Letters + WhiteSpace)
var options = ""
let
arg = getArgument(n)
isObject = arg.toLower().endsWith(".svg")
var
options = ""
content = ""
var s = getFieldValue(n, "scale")
if s.valid: dispA(d.target, options, " scale=\"$1\"", " scale=$1", [strip(s)])
if s.valid: dispA(d.target, options, if isObject: "" else: " scale=\"$1\"",
" scale=$1", [strip(s)])
s = getFieldValue(n, "height")
if s.valid: dispA(d.target, options, " height=\"$1\"", " height=$1", [strip(s)])
@@ -769,16 +774,21 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
if s.valid: dispA(d.target, options, " width=\"$1\"", " width=$1", [strip(s)])
s = getFieldValue(n, "alt")
if s.valid: dispA(d.target, options, " alt=\"$1\"", "", [strip(s)])
if s.valid:
# <object> displays its content if it cannot render the image
if isObject: dispA(d.target, content, "$1", "", [strip(s)])
else: dispA(d.target, options, " alt=\"$1\"", "", [strip(s)])
s = getFieldValue(n, "align")
if s.valid: dispA(d.target, options, " align=\"$1\"", "", [strip(s)])
if options.len > 0: options = dispF(d.target, "$1", "[$1]", [options])
let arg = getArgument(n)
if arg.valid:
dispA(d.target, result, "<img src=\"$1\"$2 />", "\\includegraphics$2{$1}",
let htmlOut = if isObject:
"<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
else: "<img src=\"$1\"$2 />"
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
[arg, options])
if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
@@ -802,7 +812,7 @@ proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) =
if parseInt(n.getFieldValue, number) > 0:
params.startLine = number
of "file":
# The ``file`` option is a Nimrod extension to the official spec, it acts
# The ``file`` option is a Nim extension to the official spec, it acts
# like it would for other directives like ``raw`` or ``cvs-table``. This
# field is dealt with in ``rst.nim`` which replaces the existing block with
# the referenced file, so we only need to ignore it here to avoid incorrect
@@ -871,7 +881,7 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
## second the code block itself. The code block can use syntax highlighting,
## which depends on the directive argument specified by the rst input, and
## may also come from the parser through the internal ``default-language``
## option to differentiate between a plain code block and nimrod's code block
## option to differentiate between a plain code block and Nim's code block
## extension.
assert n.kind == rnCodeBlock
if n.sons[2] == nil: return

View File

@@ -1,6 +1,6 @@
#nim c -t:-march=i686 --cpu:amd64 --threads:on -d:release lockfreehash.nim
import unsigned, math, hashes
import math, hashes
#------------------------------------------------------------------------------
## Memory Utility Functions

View File

@@ -951,7 +951,7 @@ when isMainModule and not defined(release):
var b = initOrderedSet[int]()
for x in [2, 4, 5]: b.incl(x)
assert($a == $b)
assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
assert(a == b) # https://github.com/Araq/Nim/issues/1413
block initBlocks:
var a: OrderedSet[int]

View File

@@ -6,7 +6,7 @@
# distribution, for details about the copyright.
#
## This module implements color handling for Nimrod. It is used by
## This module implements color handling for Nim. It is used by
## the ``graphics`` module.
import strutils

View File

@@ -328,10 +328,10 @@ proc distinguishedSlave(w: ptr Worker) {.thread.} =
if w.q.len != 0: w.cleanFlowVars
var
workers: array[MaxThreadPoolSize, TThread[ptr Worker]]
workers: array[MaxThreadPoolSize, Thread[ptr Worker]]
workersData: array[MaxThreadPoolSize, Worker]
distinguished: array[MaxDistinguishedThread, TThread[ptr Worker]]
distinguished: array[MaxDistinguishedThread, Thread[ptr Worker]]
distinguishedData: array[MaxDistinguishedThread, Worker]
when defined(nimPinToCpu):
@@ -468,7 +468,7 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} =
await(gSomeReady)
var
distinguishedLock: TLock
distinguishedLock: Lock
initLock distinguishedLock

View File

@@ -134,7 +134,7 @@ macro `[]`*(lc: ListComprehension, comp, typ: expr): expr =
## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is
## the type that will be stored inside the result seq.
##
## .. code-block:: nimrod
## .. code-block:: nim
##
## echo lc[x | (x <- 1..10, x mod 2 == 0), int]
##

View File

@@ -712,17 +712,21 @@ proc `%`*(elements: openArray[JsonNode]): JsonNode =
proc toJson(x: NimNode): NimNode {.compiletime.} =
case x.kind
of nnkBracket:
of nnkBracket: # array
result = newNimNode(nnkBracket)
for i in 0 .. <x.len:
result.add(toJson(x[i]))
of nnkTableConstr:
of nnkTableConstr: # object
result = newNimNode(nnkTableConstr)
for i in 0 .. <x.len:
assert x[i].kind == nnkExprColonExpr
x[i].expectKind nnkExprColonExpr
result.add(newNimNode(nnkExprColonExpr).add(x[i][0]).add(toJson(x[i][1])))
of nnkCurly: # empty object
result = newNimNode(nnkTableConstr)
x.expectLen(0)
else:
result = x

View File

@@ -1,5 +1,3 @@
import unsigned
type
MersenneTwister* = object
mt: array[0..623, uint32]

View File

@@ -102,8 +102,7 @@ type
## case of IPv4
{.deprecated: [TIpAddress: IpAddress].}
proc isIpAddress*(address_str: string): bool {.tags: [].}
proc parseIpAddress*(address_str: string): IpAddress
proc socketError*(socket: Socket, err: int = -1, async = false,
lastError = (-1).OSErrorCode): void
@@ -548,40 +547,6 @@ 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)
proc connect*(socket: Socket, address: string,
port = Port(0)) {.tags: [ReadIOEffect].} =
## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a
## host name. If ``address`` is a host name, this function will try each IP
## of that host name. ``htons`` is already performed on ``port`` so you must
## not do it.
##
## If ``socket`` is an SSL socket a handshake will be automatically performed.
var aiList = getAddrInfo(address, port, socket.domain)
# try all possibilities:
var success = false
var lastError: OSErrorCode
var it = aiList
while it != nil:
if connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) == 0'i32:
success = true
break
else: lastError = osLastError()
it = it.ai_next
dealloc(aiList)
if not success: raiseOSError(lastError)
when defined(ssl):
if socket.isSSL:
# RFC3546 for SNI specifies that IP addresses are not allowed.
if not isIpAddress(address):
# Discard result in case OpenSSL version doesn't support SNI, or we're
# not using TLSv1+
discard SSL_set_tlsext_host_name(socket.sslHandle, address)
let ret = SSLConnect(socket.sslHandle)
socketError(socket, ret)
when defined(ssl):
proc handshake*(socket: Socket): bool {.tags: [ReadIOEffect, WriteIOEffect].} =
## This proc needs to be called on a socket after it connects. This is
@@ -971,61 +936,6 @@ proc sendTo*(socket: Socket, address: string, port: Port,
## This is the high-level version of the above ``sendTo`` function.
result = socket.sendTo(address, port, cstring(data), data.len)
proc connectAsync(socket: Socket, name: string, port = Port(0),
af: Domain = AF_INET) {.tags: [ReadIOEffect].} =
## A variant of ``connect`` for non-blocking sockets.
##
## This procedure will immediately return, it will not block until a connection
## is made. It is up to the caller to make sure the connection has been established
## by checking (using ``select``) whether the socket is writeable.
##
## **Note**: For SSL sockets, the ``handshake`` procedure must be called
## whenever the socket successfully connects to a server.
var aiList = getAddrInfo(name, port, af)
# try all possibilities:
var success = false
var lastError: OSErrorCode
var it = aiList
while it != nil:
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen)
if ret == 0'i32:
success = true
break
else:
lastError = osLastError()
when useWinVersion:
# Windows EINTR doesn't behave same as POSIX.
if lastError.int32 == WSAEWOULDBLOCK:
success = true
break
else:
if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
success = true
break
it = it.ai_next
dealloc(aiList)
if not success: raiseOSError(lastError)
proc connect*(socket: Socket, address: string, port = Port(0),
timeout: int) {.tags: [ReadIOEffect, WriteIOEffect].} =
## Connects to server as specified by ``address`` on port specified by ``port``.
##
## The ``timeout`` paremeter specifies the time in milliseconds to allow for
## the connection to the server to be made.
socket.fd.setBlocking(false)
socket.connectAsync(address, port, socket.domain)
var s = @[socket.fd]
if selectWrite(s, timeout) != 1:
raise newException(TimeoutError, "Call to 'connect' timed out.")
else:
when defined(ssl):
if socket.isSSL:
socket.fd.setBlocking(true)
doAssert socket.handshake()
socket.fd.setBlocking(true)
proc isSsl*(socket: Socket): bool =
## Determines whether ``socket`` is a SSL socket.
@@ -1295,7 +1205,8 @@ proc parseIPv6Address(address_str: string): IpAddress =
raise newException(ValueError,
"Invalid IP Address. The address consists of too many groups")
proc parseIpAddress(address_str: string): IpAddress =
proc parseIpAddress*(address_str: string): IpAddress =
## Parses an IP address
## Raises EInvalidValue on error
if address_str == nil:
@@ -1305,8 +1216,7 @@ proc parseIpAddress(address_str: string): IpAddress =
else:
return parseIPv4Address(address_str)
proc isIpAddress(address_str: string): bool =
proc isIpAddress*(address_str: string): bool {.tags: [].} =
## Checks if a string is an IP address
## Returns true if it is, false otherwise
try:
@@ -1314,3 +1224,94 @@ proc isIpAddress(address_str: string): bool =
except ValueError:
return false
return true
proc connect*(socket: Socket, address: string,
port = Port(0)) {.tags: [ReadIOEffect].} =
## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a
## host name. If ``address`` is a host name, this function will try each IP
## of that host name. ``htons`` is already performed on ``port`` so you must
## not do it.
##
## If ``socket`` is an SSL socket a handshake will be automatically performed.
var aiList = getAddrInfo(address, port, socket.domain)
# try all possibilities:
var success = false
var lastError: OSErrorCode
var it = aiList
while it != nil:
if connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) == 0'i32:
success = true
break
else: lastError = osLastError()
it = it.ai_next
dealloc(aiList)
if not success: raiseOSError(lastError)
when defined(ssl):
if socket.isSSL:
# RFC3546 for SNI specifies that IP addresses are not allowed.
if not isIpAddress(address):
# Discard result in case OpenSSL version doesn't support SNI, or we're
# not using TLSv1+
discard SSL_set_tlsext_host_name(socket.sslHandle, address)
let ret = SSLConnect(socket.sslHandle)
socketError(socket, ret)
proc connectAsync(socket: Socket, name: string, port = Port(0),
af: Domain = AF_INET) {.tags: [ReadIOEffect].} =
## A variant of ``connect`` for non-blocking sockets.
##
## This procedure will immediately return, it will not block until a connection
## is made. It is up to the caller to make sure the connection has been established
## by checking (using ``select``) whether the socket is writeable.
##
## **Note**: For SSL sockets, the ``handshake`` procedure must be called
## whenever the socket successfully connects to a server.
var aiList = getAddrInfo(name, port, af)
# try all possibilities:
var success = false
var lastError: OSErrorCode
var it = aiList
while it != nil:
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen)
if ret == 0'i32:
success = true
break
else:
lastError = osLastError()
when useWinVersion:
# Windows EINTR doesn't behave same as POSIX.
if lastError.int32 == WSAEWOULDBLOCK:
success = true
break
else:
if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
success = true
break
it = it.ai_next
dealloc(aiList)
if not success: raiseOSError(lastError)
proc connect*(socket: Socket, address: string, port = Port(0),
timeout: int) {.tags: [ReadIOEffect, WriteIOEffect].} =
## Connects to server as specified by ``address`` on port specified by ``port``.
##
## The ``timeout`` paremeter specifies the time in milliseconds to allow for
## the connection to the server to be made.
socket.fd.setBlocking(false)
socket.connectAsync(address, port, socket.domain)
var s = @[socket.fd]
if selectWrite(s, timeout) != 1:
raise newException(TimeoutError, "Call to 'connect' timed out.")
else:
when defined(ssl):
if socket.isSSL:
socket.fd.setBlocking(true)
doAssert socket.handshake()
socket.fd.setBlocking(true)

View File

@@ -774,6 +774,7 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
res: int
res = findFirstFile(pattern, f)
if res != -1:
defer: findClose(res)
while true:
if not skipFindData(f) and
(f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) == 0'i32:
@@ -786,7 +787,6 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
pattern[dotPos+1] == '*':
yield splitFile(pattern).dir / extractFilename(ff)
if findNextFile(res, f) == 0'i32: break
findClose(res)
else: # here we use glob
var
f: Glob
@@ -795,11 +795,11 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
f.gl_pathc = 0
f.gl_pathv = nil
res = glob(pattern, 0, nil, addr(f))
defer: globfree(addr(f))
if res == 0:
for i in 0.. f.gl_pathc - 1:
assert(f.gl_pathv[i] != nil)
yield $f.gl_pathv[i]
globfree(addr(f))
type
PathComponent* = enum ## Enumeration specifying a path component.
@@ -845,6 +845,7 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
var f: WIN32_FIND_DATA
var h = findFirstFile(dir / "*", f)
if h != -1:
defer: findClose(h)
while true:
var k = pcFile
if not skipFindData(f):
@@ -856,10 +857,10 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
else: dir / extractFilename(getFilename(f))
yield (k, xx)
if findNextFile(h, f) == 0'i32: break
findClose(h)
else:
var d = opendir(dir)
if d != nil:
defer: discard closedir(d)
while true:
var x = readdir(d)
if x == nil: break
@@ -883,7 +884,6 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
if S_ISDIR(s.st_mode): k = pcDir
if S_ISLNK(s.st_mode): k = succ(k)
yield (k, y)
discard closedir(d)
iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
tags: [ReadDirEffect].} =

View File

@@ -876,7 +876,7 @@ elif not defined(useNimRtl):
let sizeRead = read(data.pErrorPipe[readIdx], addr error, sizeof(error))
if sizeRead == sizeof(error):
raiseOSError("Could not find command: '$1'. OS error: $2" %
[$data.sysCommand, $strerror(error)])
[$data.sysCommand, $strerror(error)])
return pid

View File

@@ -9,7 +9,7 @@
# TODO: Docs.
import os, unsigned, hashes
import os, hashes
when defined(linux):
import posix, epoll
@@ -118,7 +118,7 @@ elif defined(linux):
# are therefore constantly ready. (leading to 100% CPU usage).
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
raiseOSError(osLastError())
s.fds.mget(fd).events = events
s.fds[fd].events = events
else:
var event = createEventStruct(events, fd)
if s.fds[fd].events == {}:
@@ -129,7 +129,7 @@ elif defined(linux):
else:
if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0:
raiseOSError(osLastError())
s.fds.mget(fd).events = events
s.fds[fd].events = events
proc unregister*(s: var Selector, fd: SocketHandle) =
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0:
@@ -229,7 +229,7 @@ elif defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd):
modifyKQueue(s.kqFD, fd, event, EV_ADD)
for event in previousEvents-events:
modifyKQueue(s.kqFD, fd, event, EV_DELETE)
s.fds.mget(fd).events = events
s.fds[fd].events = events
proc unregister*(s: var Selector, fd: SocketHandle) =
for event in s.fds[fd].events:
@@ -298,7 +298,7 @@ elif not defined(nimdoc):
proc update*(s: var Selector, fd: SocketHandle, events: set[Event]) =
#if not s.fds.hasKey(fd):
# raise newException(ValueError, "File descriptor not found.")
s.fds.mget(fd).events = events
s.fds[fd].events = events
proc unregister*(s: var Selector, fd: SocketHandle) =
s.fds.del(fd)

View File

@@ -2960,9 +2960,9 @@ when not defined(JS): #and not defined(nimscript):
## buffer.add(line.replace("a", "0") & '\x0A')
## writeFile(filename, buffer)
var f = open(filename, bufSize=8000)
defer: close(f)
var res = TaintedString(newStringOfCap(80))
while f.readLine(res): yield res
close(f)
iterator lines*(f: File): TaintedString {.tags: [ReadIOEffect].} =
## Iterate over any line in the file `f`.

View File

@@ -138,7 +138,7 @@ proc slave(w: ptr Worker) {.thread.} =
const NumThreads = 4
var
workers: array[NumThreads, TThread[ptr Worker]]
workers: array[NumThreads, Thread[ptr Worker]]
workersData: array[NumThreads, Worker]
proc setup() =

View File

@@ -6,7 +6,7 @@ proc threadMain(a: int) {.thread.} =
discard
proc main() =
var thread: TThread[int]
var thread: Thread[int]
thread.createThread(threadMain, 0)
thread.joinThreads()

View File

@@ -3,20 +3,20 @@ discard """
"""
type
TThreadFuncArgs[T] = object of RootObj
ThreadFuncArgs[T] = object of RootObj
a: proc(): T {.thread.}
b: proc(val: T) {.thread.}
proc handleThreadFunc(arg: TThreadFuncArgs[int]){.thread.} =
proc handleThreadFunc(arg: ThreadFuncArgs[int]){.thread.} =
var fn = arg.a
var callback = arg.b
var output = fn()
callback(output)
proc `@||->`*[T](fn: proc(): T {.thread.},
callback: proc(val: T){.thread.}): TThread[TThreadFuncArgs[T]] =
var thr: TThread[TThreadFuncArgs[T]]
var args: TThreadFuncArgs[T]
callback: proc(val: T){.thread.}): Thread[ThreadFuncArgs[T]] =
var thr: Thread[ThreadFuncArgs[T]]
var args: ThreadFuncArgs[T]
args.a = fn
args.b = callback
createThread(thr, handleThreadFunc, args)

View File

@@ -1,4 +1,4 @@
## Command line parsing module for Nimrod.
## Command line parsing module for Nim.
##
## `Nim <http://nim-lang.org>`_ provides the `parseopt module
## <http://nim-lang.org/parseopt.html>`_ to parse options from the

View File

@@ -1,5 +1,5 @@
import
streams, md5, sockets, unsigned,
streams, md5, sockets,
sg_packets, zlib_helpers, idgen
type
TClientType* = enum

View File

@@ -1,5 +1,5 @@
import
sockets, times, streams, streams_enh, tables, json, os, unsigned,
sockets, times, streams, streams_enh, tables, json, os,
sg_packets, sg_assets, md5, server_utils, client_helpers
var
dirServer: PServer

View File

@@ -8,10 +8,6 @@ from strutils import
`%`,
ffDecimal
from unsigned import
`shr`,
`and`
type
TColor* = tuple[r, g, b, a: TR]

View File

@@ -1,8 +1,6 @@
# bug #1638
import unsigned
let v1 = 7
let v2 = 7'u64

View File

@@ -5,8 +5,6 @@ true'''
"""
# bug 1420
import unsigned
var x = 40'u32
var y = 30'u32
echo x > y # works

View File

@@ -1,6 +1,4 @@
import unsigned
# Tests unsigned literals and implicit conversion between uints and ints
# Passes if it compiles

View File

@@ -1,5 +1,3 @@
import unsigned
discard """
errormsg: "number 0x123'u8 out of valid range"
"""

View File

@@ -1,6 +1,6 @@
when false:
template lock(a, b: ptr TLock; body: stmt) =
template lock(a, b: ptr Lock; body: stmt) =
if cast[ByteAddress](a) < cast[ByteAddress](b):
pthread_mutex_lock(a)
pthread_mutex_lock(b)

View File

@@ -11,7 +11,7 @@ type
of mLine: data: string
var
producer, consumer: TThread[void]
producer, consumer: Thread[void]
chan: TChannel[TMsg]
printedLines = 0

View File

@@ -8,7 +8,7 @@ discard """
import os
var
thr: array [0..5, TThread[tuple[a, b: int]]]
thr: array [0..5, Thread[tuple[a, b: int]]]
proc doNothing() = discard

View File

@@ -8,7 +8,7 @@ discard """
import os
var
thr: array [0..5, TThread[tuple[a, b: int]]]
thr: array [0..5, Thread[tuple[a, b: int]]]
proc doNothing() = discard

View File

@@ -6,7 +6,7 @@ discard """
var
global: string = "test string"
t: TThread[void]
t: Thread[void]
proc horrible() {.thread.} =
global = "string in thread local heap!"

View File

@@ -15,7 +15,7 @@ proc doAction(outC: PComm) {.thread.} =
send(outC[], i)
var
thr: TThread[PComm]
thr: Thread[PComm]
chan: TChannel[int]
open(chan)

View File

@@ -1,7 +1,7 @@
import db_sqlite
var db: TDbConn
var db: DbConn
exec(db, sql"create table blabla()")

View File

@@ -52,7 +52,7 @@ proc Connect*(irc: var TIRC, nick: string, host: string, port: int = 6667) =
connect(irc.Socket, host, TPort(port), TDomain.AF_INET)
send(irc.Socket,"USER " & nick & " " & nick & " " & nick & " " & nick & "\r\L")
send(irc.Socket,"NICK " & nick & "\r\L")
var thread: TThread[TIRC]
var thread: Thread[TIRC]
createThread(thread, handleData, irc)
irc.Thread = thread