diff options
author | Oscar Campbell <oscar@campbell.nu> | 2015-05-25 19:51:58 +0200 |
---|---|---|
committer | Oscar Campbell <oscar@campbell.nu> | 2015-05-25 19:51:58 +0200 |
commit | f6c12853ea996ef6307d0e5fd6738d0aaa2bd1e7 (patch) | |
tree | 1d9e468089a169fc9fd44678c19194eaa2c8a3c8 | |
parent | 625299e861173266d0393ffdd76e66be9cb0c34d (diff) | |
parent | 71561bef5846fbbfea1f77ecba1f9d6d7426ca43 (diff) | |
download | Nim-f6c12853ea996ef6307d0e5fd6738d0aaa2bd1e7.tar.gz |
Merge remote-tracking branch 'upstream/devel' into devel
-rw-r--r-- | compiler/nimsuggest/nimsuggest.nim | 8 | ||||
-rw-r--r-- | doc/manual/stmts.txt | 6 | ||||
-rw-r--r-- | doc/manual/types.txt | 2 | ||||
-rw-r--r-- | lib/pure/algorithm.nim | 5 | ||||
-rw-r--r-- | lib/pure/streams.nim | 99 | ||||
-rw-r--r-- | lib/system.nim | 8 | ||||
-rw-r--r-- | lib/system/gc.nim | 9 | ||||
-rw-r--r-- | lib/system/gc_ms.nim | 9 |
8 files changed, 130 insertions, 16 deletions
diff --git a/compiler/nimsuggest/nimsuggest.nim b/compiler/nimsuggest/nimsuggest.nim index 3b4aa658d..2c785d118 100644 --- a/compiler/nimsuggest/nimsuggest.nim +++ b/compiler/nimsuggest/nimsuggest.nim @@ -119,9 +119,8 @@ proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int) = gTrackPos = newLineInfo(dirtyIdx, line, col) gErrorCounter = 0 if not isKnownFile: - compileProject(dirtyIdx) - else: compileProject() + compileProject(dirtyIdx) proc executeEPC(cmd: IdeCmd, args: SexpNode) = let @@ -192,8 +191,6 @@ proc parseCmdLine(cmd: string) = execute(gIdeCmd, orig, dirtyfile, line, col-1) proc serve() = - # do not stop after the first error: - msgs.gErrorMax = high(int) case gMode: of mstdin: echo Help @@ -278,6 +275,9 @@ proc mainCommand = # current path is always looked first for modules prependStr(searchPaths, gProjectPath) + # do not stop after the first error: + msgs.gErrorMax = high(int) + compileProject() serve() proc processCmdLine*(pass: TCmdLinePass, cmd: string) = diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt index 7b4ea9e6d..32c01dccb 100644 --- a/doc/manual/stmts.txt +++ b/doc/manual/stmts.txt @@ -176,9 +176,9 @@ The rules for compile-time computability are: 1. Literals are compile-time computable. 2. Type conversions are compile-time computable. 3. Procedure calls of the form ``p(X)`` are compile-time computable if - ``p`` is a proc without side-effects (see the `noSideEffect pragma`_ - for details) and if ``X`` is a (possibly empty) list of compile-time - computable arguments. + ``p`` is a proc without side-effects (see the `noSideEffect pragma + <#pragmas-nosideeffect-pragma>`_ for details) and if ``X`` is a + (possibly empty) list of compile-time computable arguments. Constants cannot be of type ``ptr``, ``ref``, ``var`` or ``object``, nor can diff --git a/doc/manual/types.txt b/doc/manual/types.txt index 5e3e98ce6..81ae9d6b4 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -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 of the following conditions hold: 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``. 4) The procedure is anonymous. diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 46d049f14..0eafb316a 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -243,7 +243,7 @@ template sortedByIt*(seq1, op: expr): expr = proc product*[T](x: openArray[seq[T]]): seq[seq[T]] = ## produces the Cartesian product of the array. Warning: complexity ## may explode. - result = @[] + result = newSeq[seq[T]]() if x.len == 0: return if x.len == 1: @@ -253,8 +253,7 @@ proc product*[T](x: openArray[seq[T]]): seq[seq[T]] = indexes = newSeq[int](x.len) initial = newSeq[int](x.len) index = 0 - # replace with newSeq as soon as #853 is fixed - var next: seq[T] = @[] + var next = newSeq[T]() next.setLen(x.len) for i in 0..(x.len-1): if len(x[i]) == 0: return diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index e706f2016..77698d329 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -1,7 +1,7 @@ # # # Nim's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -31,6 +31,8 @@ type getPositionImpl*: proc (s: Stream): int {.nimcall, tags: [], gcsafe.} readDataImpl*: proc (s: Stream, buffer: pointer, 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, 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. 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) = ## low level proc that writes an untyped `buffer` of `bufLen` size ## 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): 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 = ## reads a char from the stream `s`. Raises `EIO` if an error occurred. ## Returns '\0' as an EOF marker. 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 = ## reads a bool from the stream `s`. Raises `EIO` if an error occurred. 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 = ## reads an int8 from the stream `s`. Raises `EIO` if an error occurred. 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 = ## reads an int16 from the stream `s`. Raises `EIO` if an error occurred. 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 = ## reads an int32 from the stream `s`. Raises `EIO` if an error occurred. 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 = ## reads an int64 from the stream `s`. Raises `EIO` if an error occurred. 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 = ## reads a float32 from the stream `s`. Raises `EIO` if an error occurred. 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 = ## reads a float64 from the stream `s`. Raises `EIO` if an error occurred. 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 = ## reads a string of length `length` from the stream `s`. Raises `EIO` if ## an error occurred. @@ -161,6 +206,13 @@ proc readStr*(s: Stream, length: int): TaintedString = var L = readData(s, addr(string(result)[0]), length) 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 = ## reads a line of text from the stream `s` into `line`. `line` must not be ## ``nil``! May throw an IO exception. @@ -181,6 +233,17 @@ proc readLine*(s: Stream, line: var TaintedString): bool = line.string.add(c) 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 = ## Reads a line from a stream `s`. Note: This is not very efficient. Raises ## `EIO` if an error occurred. @@ -195,6 +258,13 @@ proc readLine*(s: Stream): TaintedString = else: 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 StringStream* = ref StringStreamObj ## a stream that encapsulates a string 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) 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) = var s = StringStream(s) if bufLen <= 0: @@ -245,6 +321,7 @@ proc newStringStream*(s: string = ""): StringStream = result.setPositionImpl = ssSetPosition result.getPositionImpl = ssGetPosition result.readDataImpl = ssReadData + result.peekDataImpl = ssPeekData result.writeDataImpl = ssWriteData when not defined(js): @@ -266,6 +343,11 @@ when not defined(js): proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int = 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) = if writeBuffer(FileStream(s).f, buffer, bufLen) != bufLen: @@ -280,6 +362,7 @@ when not defined(js): result.setPositionImpl = fsSetPosition result.getPositionImpl = fsGetPosition result.readDataImpl = fsReadData + result.peekDataImpl = fsPeekData result.writeDataImpl = fsWriteData result.flushImpl = fsFlush @@ -329,6 +412,9 @@ else: proc hsReadData(s: FileHandleStream, buffer: pointer, bufLen: int): int = result = posix.read(s.handle, buffer, bufLen) 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) = if posix.write(s.handle, buffer, bufLen) != bufLen: @@ -344,6 +430,7 @@ else: result.setPosition = hsSetPosition result.getPosition = hsGetPosition result.readData = hsReadData + result.peekData = hsPeekData result.writeData = hsWriteData proc newFileHandleStream*(filename: string, @@ -361,3 +448,13 @@ else: var handle = open(filename, flags) if handle < 0: raise newEOS("posix.open() call failed") 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 diff --git a/lib/system.nim b/lib/system.nim index 1e6f76f3d..a4b053ca7 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -61,7 +61,7 @@ const on* = true ## alias for ``true`` off* = false ## alias for ``false`` -{.push warning[GcMem]: off.} +{.push warning[GcMem]: off, warning[Uninit]: off.} {.push hints: off.} 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 ## ``echo`` is very often used for debugging convenience. If you want to use ## ``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. proc debugEcho*(x: varargs[expr, `$`]) {.magic: "Echo", noSideEffect, tags: [], raises: [].} ## 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 - ## routines marked as `noSideEffect <manual.html#nosideeffect-pragma>`_. + ## routines marked as `noSideEffect <manual.html#pragmas-nosideeffect-pragma>`_. template newException*(exceptn: typedesc, message: string): expr = ## 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. discard -{.pop.} #{.push warning[GcMem]: off.} +{.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.} diff --git a/lib/system/gc.nim b/lib/system/gc.nim index c4374d00c..e0d1006d9 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -922,6 +922,15 @@ else: if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. var max = cast[ByteAddress](gch.stackBottom) 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: while sp <% max - 8*sizeof(pointer): gcMark(gch, cast[PStackSlice](sp)[0]) diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index e287bf5d9..a0699f46a 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -514,6 +514,15 @@ else: if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. var max = cast[ByteAddress](gch.stackBottom) 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: while sp <% max - 8*sizeof(pointer): gcMark(gch, cast[PStackSlice](sp)[0]) |