Merge remote-tracking branch 'upstream/devel' into devel

This commit is contained in:
Oscar Campbell 2015-05-25 19:51:58 +02:00
commit f6c12853ea
8 changed files with 130 additions and 16 deletions

View file

@ -119,9 +119,8 @@ proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int) =
gTrackPos = newLineInfo(dirtyIdx, line, col) gTrackPos = newLineInfo(dirtyIdx, line, col)
gErrorCounter = 0 gErrorCounter = 0
if not isKnownFile: if not isKnownFile:
compileProject(dirtyIdx)
else:
compileProject() compileProject()
compileProject(dirtyIdx)
proc executeEPC(cmd: IdeCmd, args: SexpNode) = proc executeEPC(cmd: IdeCmd, args: SexpNode) =
let let
@ -192,8 +191,6 @@ proc parseCmdLine(cmd: string) =
execute(gIdeCmd, orig, dirtyfile, line, col-1) execute(gIdeCmd, orig, dirtyfile, line, col-1)
proc serve() = proc serve() =
# do not stop after the first error:
msgs.gErrorMax = high(int)
case gMode: case gMode:
of mstdin: of mstdin:
echo Help echo Help
@ -278,6 +275,9 @@ proc mainCommand =
# current path is always looked first for modules # current path is always looked first for modules
prependStr(searchPaths, gProjectPath) prependStr(searchPaths, gProjectPath)
# do not stop after the first error:
msgs.gErrorMax = high(int)
compileProject()
serve() serve()
proc processCmdLine*(pass: TCmdLinePass, cmd: string) = proc processCmdLine*(pass: TCmdLinePass, cmd: string) =

View file

@ -176,9 +176,9 @@ The rules for compile-time computability are:
1. Literals are compile-time computable. 1. Literals are compile-time computable.
2. Type conversions are compile-time computable. 2. Type conversions are compile-time computable.
3. Procedure calls of the form ``p(X)`` are compile-time computable if 3. Procedure calls of the form ``p(X)`` are compile-time computable if
``p`` is a proc without side-effects (see the `noSideEffect pragma`_ ``p`` is a proc without side-effects (see the `noSideEffect pragma
for details) and if ``X`` is a (possibly empty) list of compile-time <#pragmas-nosideeffect-pragma>`_ for details) and if ``X`` is a
computable arguments. (possibly empty) list of compile-time computable arguments.
Constants cannot be of type ``ptr``, ``ref``, ``var`` or ``object``, nor can Constants cannot be of type ``ptr``, ``ref``, ``var`` or ``object``, nor can

View file

@ -963,7 +963,7 @@ Most calling conventions exist only for the Windows 32-bit platform.
Assigning/passing a procedure to a procedural variable is only allowed if one Assigning/passing a procedure to a procedural variable is only allowed if one
of the following conditions hold: of the following conditions hold:
1) The procedure that is accessed resides in the current module. 1) The procedure that is accessed resides in the current module.
2) The procedure is marked with the ``procvar`` pragma (see `procvar pragma`_). 2) The procedure is marked with the ``procvar`` pragma (see `procvar pragma <#pragmas-procvar-pragma>`_).
3) The procedure has a calling convention that differs from ``nimcall``. 3) The procedure has a calling convention that differs from ``nimcall``.
4) The procedure is anonymous. 4) The procedure is anonymous.

View file

@ -243,7 +243,7 @@ template sortedByIt*(seq1, op: expr): expr =
proc product*[T](x: openArray[seq[T]]): seq[seq[T]] = proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
## produces the Cartesian product of the array. Warning: complexity ## produces the Cartesian product of the array. Warning: complexity
## may explode. ## may explode.
result = @[] result = newSeq[seq[T]]()
if x.len == 0: if x.len == 0:
return return
if x.len == 1: if x.len == 1:
@ -253,8 +253,7 @@ proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
indexes = newSeq[int](x.len) indexes = newSeq[int](x.len)
initial = newSeq[int](x.len) initial = newSeq[int](x.len)
index = 0 index = 0
# replace with newSeq as soon as #853 is fixed var next = newSeq[T]()
var next: seq[T] = @[]
next.setLen(x.len) next.setLen(x.len)
for i in 0..(x.len-1): for i in 0..(x.len-1):
if len(x[i]) == 0: return if len(x[i]) == 0: return

View file

@ -1,7 +1,7 @@
# #
# #
# Nim's Runtime Library # Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2015 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -31,6 +31,8 @@ type
getPositionImpl*: proc (s: Stream): int {.nimcall, tags: [], gcsafe.} getPositionImpl*: proc (s: Stream): int {.nimcall, tags: [], gcsafe.}
readDataImpl*: proc (s: Stream, buffer: pointer, readDataImpl*: proc (s: Stream, buffer: pointer,
bufLen: int): int {.nimcall, tags: [ReadIOEffect], gcsafe.} bufLen: int): int {.nimcall, tags: [ReadIOEffect], gcsafe.}
peekDataImpl*: proc (s: Stream, buffer: pointer,
bufLen: int): int {.nimcall, tags: [ReadIOEffect], gcsafe.}
writeDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int) {.nimcall, writeDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int) {.nimcall,
tags: [WriteIOEffect], gcsafe.} tags: [WriteIOEffect], gcsafe.}
flushImpl*: proc (s: Stream) {.nimcall, tags: [WriteIOEffect], gcsafe.} flushImpl*: proc (s: Stream) {.nimcall, tags: [WriteIOEffect], gcsafe.}
@ -84,6 +86,11 @@ proc readData*(s, unused: Stream, buffer: pointer,
## low level proc that reads data into an untyped `buffer` of `bufLen` size. ## low level proc that reads data into an untyped `buffer` of `bufLen` size.
result = s.readDataImpl(s, buffer, bufLen) result = s.readDataImpl(s, buffer, bufLen)
proc peekData*(s: Stream, buffer: pointer, bufLen: int): int =
## low level proc that reads data into an untyped `buffer` of `bufLen` size
## without moving stream position
result = s.peekDataImpl(s, buffer, bufLen)
proc writeData*(s: Stream, buffer: pointer, bufLen: int) = proc writeData*(s: Stream, buffer: pointer, bufLen: int) =
## low level proc that writes an untyped `buffer` of `bufLen` size ## low level proc that writes an untyped `buffer` of `bufLen` size
## to the stream `s`. ## to the stream `s`.
@ -121,39 +128,77 @@ proc read[T](s: Stream, result: var T) =
if readData(s, addr(result), sizeof(T)) != sizeof(T): if readData(s, addr(result), sizeof(T)) != sizeof(T):
raise newEIO("cannot read from stream") raise newEIO("cannot read from stream")
proc peek[T](s: Stream, result: var T) =
## generic peek procedure. Peeks `result` from the stream `s`.
if peekData(s, addr(result), sizeof(T)) != sizeof(T):
raise newEIO("cannot read from stream")
proc readChar*(s: Stream): char = proc readChar*(s: Stream): char =
## reads a char from the stream `s`. Raises `EIO` if an error occurred. ## reads a char from the stream `s`. Raises `EIO` if an error occurred.
## Returns '\0' as an EOF marker. ## Returns '\0' as an EOF marker.
if readData(s, addr(result), sizeof(result)) != 1: result = '\0' if readData(s, addr(result), sizeof(result)) != 1: result = '\0'
proc peekChar*(s: Stream): char =
## peeks a char from the stream `s`. Raises `EIO` if an error occurred.
## Returns '\0' as an EOF marker.
if peekData(s, addr(result), sizeof(result)) != 1: result = '\0'
proc readBool*(s: Stream): bool = proc readBool*(s: Stream): bool =
## reads a bool from the stream `s`. Raises `EIO` if an error occurred. ## reads a bool from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc peekBool*(s: Stream): bool =
## peeks a bool from the stream `s`. Raises `EIO` if an error occured.
peek(s, result)
proc readInt8*(s: Stream): int8 = proc readInt8*(s: Stream): int8 =
## reads an int8 from the stream `s`. Raises `EIO` if an error occurred. ## reads an int8 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc peekInt8*(s: Stream): int8 =
## peeks an int8 from the stream `s`. Raises `EIO` if an error occurred.
peek(s, result)
proc readInt16*(s: Stream): int16 = proc readInt16*(s: Stream): int16 =
## reads an int16 from the stream `s`. Raises `EIO` if an error occurred. ## reads an int16 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc peekInt16*(s: Stream): int16 =
## peeks an int16 from the stream `s`. Raises `EIO` if an error occurred.
peek(s, result)
proc readInt32*(s: Stream): int32 = proc readInt32*(s: Stream): int32 =
## reads an int32 from the stream `s`. Raises `EIO` if an error occurred. ## reads an int32 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc peekInt32*(s: Stream): int32 =
## peeks an int32 from the stream `s`. Raises `EIO` if an error occurred.
peek(s, result)
proc readInt64*(s: Stream): int64 = proc readInt64*(s: Stream): int64 =
## reads an int64 from the stream `s`. Raises `EIO` if an error occurred. ## reads an int64 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc peekInt64*(s: Stream): int64 =
## peeks an int64 from the stream `s`. Raises `EIO` if an error occurred.
peek(s, result)
proc readFloat32*(s: Stream): float32 = proc readFloat32*(s: Stream): float32 =
## reads a float32 from the stream `s`. Raises `EIO` if an error occurred. ## reads a float32 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc peekFloat32*(s: Stream): float32 =
## peeks a float32 from the stream `s`. Raises `EIO` if an error occurred.
peek(s, result)
proc readFloat64*(s: Stream): float64 = proc readFloat64*(s: Stream): float64 =
## reads a float64 from the stream `s`. Raises `EIO` if an error occurred. ## reads a float64 from the stream `s`. Raises `EIO` if an error occurred.
read(s, result) read(s, result)
proc peekFloat64*(s: Stream): float64 =
## peeks a float64 from the stream `s`. Raises `EIO` if an error occurred.
peek(s, result)
proc readStr*(s: Stream, length: int): TaintedString = proc readStr*(s: Stream, length: int): TaintedString =
## reads a string of length `length` from the stream `s`. Raises `EIO` if ## reads a string of length `length` from the stream `s`. Raises `EIO` if
## an error occurred. ## an error occurred.
@ -161,6 +206,13 @@ proc readStr*(s: Stream, length: int): TaintedString =
var L = readData(s, addr(string(result)[0]), length) var L = readData(s, addr(string(result)[0]), length)
if L != length: setLen(result.string, L) if L != length: setLen(result.string, L)
proc peekStr*(s: Stream, length: int): TaintedString =
## peeks a string of length `length` from the stream `s`. Raises `EIO` if
## an error occurred.
result = newString(length).TaintedString
var L = peekData(s, addr(string(result)[0]), length)
if L != length: setLen(result.string, L)
proc readLine*(s: Stream, line: var TaintedString): bool = proc readLine*(s: Stream, line: var TaintedString): bool =
## reads a line of text from the stream `s` into `line`. `line` must not be ## reads a line of text from the stream `s` into `line`. `line` must not be
## ``nil``! May throw an IO exception. ## ``nil``! May throw an IO exception.
@ -181,6 +233,17 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
line.string.add(c) line.string.add(c)
result = true result = true
proc peekLine*(s: Stream, line: var TaintedString): bool =
## peeks a line of text from the stream `s` into `line`. `line` must not be
## ``nil``! May throw an IO exception.
## A line of text may be delimited by ``CR``, ``LF`` or
## ``CRLF``. The newline character(s) are not part of the returned string.
## Returns ``false`` if the end of the file has been reached, ``true``
## otherwise. If ``false`` is returned `line` contains no new data.
let pos = getPosition(s)
defer: setPosition(s, pos)
readLine(s, line)
proc readLine*(s: Stream): TaintedString = proc readLine*(s: Stream): TaintedString =
## Reads a line from a stream `s`. Note: This is not very efficient. Raises ## Reads a line from a stream `s`. Note: This is not very efficient. Raises
## `EIO` if an error occurred. ## `EIO` if an error occurred.
@ -195,6 +258,13 @@ proc readLine*(s: Stream): TaintedString =
else: else:
result.string.add(c) result.string.add(c)
proc peekLine*(s: Stream): TaintedString =
## Peeks a line from a stream `s`. Note: This is not very efficient. Raises
## `EIO` if an error occurred.
let pos = getPosition(s)
defer: setPosition(s, pos)
readLine(s)
type type
StringStream* = ref StringStreamObj ## a stream that encapsulates a string StringStream* = ref StringStreamObj ## a stream that encapsulates a string
StringStreamObj* = object of StreamObj StringStreamObj* = object of StreamObj
@ -222,6 +292,12 @@ proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int =
copyMem(buffer, addr(s.data[s.pos]), result) copyMem(buffer, addr(s.data[s.pos]), result)
inc(s.pos, result) inc(s.pos, result)
proc ssPeekData(s: Stream, buffer: pointer, bufLen: int): int =
var s = StringStream(s)
result = min(bufLen, s.data.len - s.pos)
if result > 0:
copyMem(buffer, addr(s.data[s.pos]), result)
proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) = proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) =
var s = StringStream(s) var s = StringStream(s)
if bufLen <= 0: if bufLen <= 0:
@ -245,6 +321,7 @@ proc newStringStream*(s: string = ""): StringStream =
result.setPositionImpl = ssSetPosition result.setPositionImpl = ssSetPosition
result.getPositionImpl = ssGetPosition result.getPositionImpl = ssGetPosition
result.readDataImpl = ssReadData result.readDataImpl = ssReadData
result.peekDataImpl = ssPeekData
result.writeDataImpl = ssWriteData result.writeDataImpl = ssWriteData
when not defined(js): when not defined(js):
@ -266,6 +343,11 @@ when not defined(js):
proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int = proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int =
result = readBuffer(FileStream(s).f, buffer, bufLen) result = readBuffer(FileStream(s).f, buffer, bufLen)
proc fsPeekData(s: Stream, buffer: pointer, bufLen: int): int =
let pos = fsGetPosition(s)
defer: fsSetPosition(s, pos)
result = readBuffer(FileStream(s).f, buffer, bufLen)
proc fsWriteData(s: Stream, buffer: pointer, bufLen: int) = proc fsWriteData(s: Stream, buffer: pointer, bufLen: int) =
if writeBuffer(FileStream(s).f, buffer, bufLen) != bufLen: if writeBuffer(FileStream(s).f, buffer, bufLen) != bufLen:
@ -280,6 +362,7 @@ when not defined(js):
result.setPositionImpl = fsSetPosition result.setPositionImpl = fsSetPosition
result.getPositionImpl = fsGetPosition result.getPositionImpl = fsGetPosition
result.readDataImpl = fsReadData result.readDataImpl = fsReadData
result.peekDataImpl = fsPeekData
result.writeDataImpl = fsWriteData result.writeDataImpl = fsWriteData
result.flushImpl = fsFlush result.flushImpl = fsFlush
@ -329,6 +412,9 @@ else:
proc hsReadData(s: FileHandleStream, buffer: pointer, bufLen: int): int = proc hsReadData(s: FileHandleStream, buffer: pointer, bufLen: int): int =
result = posix.read(s.handle, buffer, bufLen) result = posix.read(s.handle, buffer, bufLen)
inc(s.pos, result) inc(s.pos, result)
proc hsPeekData(s: FileHandleStream, buffer: pointer, bufLen: int): int =
result = posix.read(s.handle, buffer, bufLen)
proc hsWriteData(s: FileHandleStream, buffer: pointer, bufLen: int) = proc hsWriteData(s: FileHandleStream, buffer: pointer, bufLen: int) =
if posix.write(s.handle, buffer, bufLen) != bufLen: if posix.write(s.handle, buffer, bufLen) != bufLen:
@ -344,6 +430,7 @@ else:
result.setPosition = hsSetPosition result.setPosition = hsSetPosition
result.getPosition = hsGetPosition result.getPosition = hsGetPosition
result.readData = hsReadData result.readData = hsReadData
result.peekData = hsPeekData
result.writeData = hsWriteData result.writeData = hsWriteData
proc newFileHandleStream*(filename: string, proc newFileHandleStream*(filename: string,
@ -361,3 +448,13 @@ else:
var handle = open(filename, flags) var handle = open(filename, flags)
if handle < 0: raise newEOS("posix.open() call failed") if handle < 0: raise newEOS("posix.open() call failed")
result = newFileHandleStream(handle) result = newFileHandleStream(handle)
when defined(testing):
var ss = newStringStream("The quick brown fox jumped over the lazy dog.\nThe lazy dog ran")
assert(ss.getPosition == 0)
assert(ss.peekStr(5) == "The q")
assert(ss.getPosition == 0) # haven't moved
assert(ss.readStr(5) == "The q")
assert(ss.getPosition == 5) # did move
assert(ss.peekLine() == "uick brown fox jumped over the lazy dog.")
assert(ss.getPosition == 5) # haven't moved

View file

@ -61,7 +61,7 @@ const
on* = true ## alias for ``true`` on* = true ## alias for ``true``
off* = false ## alias for ``false`` off* = false ## alias for ``false``
{.push warning[GcMem]: off.} {.push warning[GcMem]: off, warning[Uninit]: off.}
{.push hints: off.} {.push hints: off.}
type type
@ -2248,14 +2248,14 @@ proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
## Unlike other IO operations this is guaranteed to be thread-safe as ## Unlike other IO operations this is guaranteed to be thread-safe as
## ``echo`` is very often used for debugging convenience. If you want to use ## ``echo`` is very often used for debugging convenience. If you want to use
## ``echo`` inside a `proc without side effects ## ``echo`` inside a `proc without side effects
## <manual.html#nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_ ## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho <#debugEcho>`_
## instead. ## instead.
proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect, proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect,
tags: [], raises: [].} tags: [], raises: [].}
## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho`` ## Same as `echo <#echo>`_, but as a special semantic rule, ``debugEcho``
## pretends to be free of side effects, so that it can be used for debugging ## pretends to be free of side effects, so that it can be used for debugging
## routines marked as `noSideEffect <manual.html#nosideeffect-pragma>`_. ## routines marked as `noSideEffect <manual.html#pragmas-nosideeffect-pragma>`_.
template newException*(exceptn: typedesc, message: string): expr = template newException*(exceptn: typedesc, message: string): expr =
## creates an exception object of type ``exceptn`` and sets its ``msg`` field ## creates an exception object of type ``exceptn`` and sets its ``msg`` field
@ -3273,4 +3273,4 @@ proc xlen*[T](x: seq[T]): int {.magic: "XLenSeq", noSideEffect.} =
## This is an optimization that rarely makes sense. ## This is an optimization that rarely makes sense.
discard discard
{.pop.} #{.push warning[GcMem]: off.} {.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.}

View file

@ -922,6 +922,15 @@ else:
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
var max = cast[ByteAddress](gch.stackBottom) var max = cast[ByteAddress](gch.stackBottom)
var sp = cast[ByteAddress](addr(registers)) var sp = cast[ByteAddress](addr(registers))
when defined(amd64):
# words within the jmp_buf structure may not be properly aligned.
let regEnd = sp +% sizeof(registers)
while sp <% regEnd:
gcMark(gch, cast[PPointer](sp)[])
gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[])
sp = sp +% sizeof(pointer)
# Make sure sp is word-aligned
sp = sp and not (sizeof(pointer) - 1)
# loop unrolled: # loop unrolled:
while sp <% max - 8*sizeof(pointer): while sp <% max - 8*sizeof(pointer):
gcMark(gch, cast[PStackSlice](sp)[0]) gcMark(gch, cast[PStackSlice](sp)[0])

View file

@ -514,6 +514,15 @@ else:
if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
var max = cast[ByteAddress](gch.stackBottom) var max = cast[ByteAddress](gch.stackBottom)
var sp = cast[ByteAddress](addr(registers)) var sp = cast[ByteAddress](addr(registers))
when defined(amd64):
# words within the jmp_buf structure may not be properly aligned.
let regEnd = sp +% sizeof(registers)
while sp <% regEnd:
gcMark(gch, cast[PPointer](sp)[])
gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[])
sp = sp +% sizeof(pointer)
# Make sure sp is word-aligned
sp = sp and not (sizeof(pointer) - 1)
# loop unrolled: # loop unrolled:
while sp <% max - 8*sizeof(pointer): while sp <% max - 8*sizeof(pointer):
gcMark(gch, cast[PStackSlice](sp)[0]) gcMark(gch, cast[PStackSlice](sp)[0])