summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/nimsuggest/nimsuggest.nim8
-rw-r--r--doc/manual/stmts.txt6
-rw-r--r--doc/manual/types.txt2
-rw-r--r--lib/pure/algorithm.nim5
-rw-r--r--lib/pure/streams.nim99
-rw-r--r--lib/system.nim8
-rw-r--r--lib/system/gc.nim9
-rw-r--r--lib/system/gc_ms.nim9
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])