summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-07-26 00:46:41 +0200
committerAraq <rumpf_a@web.de>2011-07-26 00:46:41 +0200
commit0e7f2ca3f1607ad51e7e69e1b367450a8299c526 (patch)
tree41d98c00a9cd763ec7731d0b9b94ce0757a99cca
parent3ac9012361f6d6642455c0bc81cb9f49ae5e844a (diff)
downloadNim-0e7f2ca3f1607ad51e7e69e1b367450a8299c526.tar.gz
bugfixes; added events module, sequtils module
-rwxr-xr-xcompiler/rst.nim10
-rwxr-xr-xcompiler/types.nim2
-rwxr-xr-xcontributors.txt1
-rwxr-xr-xdoc/lib.txt11
-rwxr-xr-xexamples/allany.nim15
-rw-r--r--lib/pure/collections/sequtils.nim59
-rw-r--r--lib/pure/events.nim83
-rwxr-xr-xlib/system/sysio.nim14
-rw-r--r--tests/accept/run/tevents.nim48
-rw-r--r--tests/accept/run/tsequtils.nim55
-rwxr-xr-xtools/nimgrep.nim6
-rwxr-xr-xweb/news.txt2
-rwxr-xr-xweb/nimrod.ini1
13 files changed, 292 insertions, 15 deletions
diff --git a/compiler/rst.nim b/compiler/rst.nim
index 53079ebed..87a5e194e 100755
--- a/compiler/rst.nim
+++ b/compiler/rst.nim
@@ -859,10 +859,12 @@ proc parseField(p: var TRstParser): PRstNode =
 
 proc parseFields(p: var TRstParser): PRstNode = 
   result = nil
-  if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx + 1].symbol == ":"): 
-    var col = p.tok[p.idx].ival   # BUGFIX!
+  var atStart = p.idx == 0 and p.tok[0].symbol == ":"
+  if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx + 1].symbol == ":") or
+      atStart:
+    var col = if atStart: p.tok[p.idx].col else: p.tok[p.idx].ival
     result = newRstNode(rnFieldList)
-    inc(p.idx)
+    if not atStart: inc(p.idx)
     while true: 
       addSon(result, parseField(p))
       if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and
@@ -1307,7 +1309,7 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
     of rnParagraph: nil
     of rnDefList: a = parseDefinitionList(p)
     of rnFieldList: 
-      dec(p.idx)
+      if p.idx > 0: dec(p.idx)
       a = parseFields(p)
     of rnTransition: a = parseTransition(p)
     of rnHeadline: a = parseHeadline(p)
diff --git a/compiler/types.nim b/compiler/types.nim
index 01504ec56..83426bed7 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -896,7 +896,7 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
     if typ.callConv == ccClosure: result = 2 * ptrSize
     else: result = ptrSize
     a = ptrSize
-  of tyNil, tyCString, tyString, tySequence, tyPtr, tyRef, tyOpenArray: 
+  of tyNil, tyCString, tyString, tySequence, tyPtr, tyRef, tyVar, tyOpenArray: 
     result = ptrSize
     a = result
   of tyArray, tyArrayConstr: 
diff --git a/contributors.txt b/contributors.txt
index bc3f41a67..4d0e2bb51 100755
--- a/contributors.txt
+++ b/contributors.txt
@@ -2,6 +2,7 @@ Comex
 Eric Doughty-Papassideris
 Philippe Lhoste
 Mario Ray Mahardhika
+Alex Mitchell
 Dominik Picheta
 Jonathan Plona
 Alexander Rødseth
diff --git a/doc/lib.txt b/doc/lib.txt
index 12890d33d..942e2de26 100755
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -60,6 +60,9 @@ Collections and algorithms
   Implementation of a queue. The underlying implementation uses a ``seq``.
 * `intsets <intsets.html>`_
   Efficient implementation of a set of ints as a sparse bit set.
+* `sequtils <sequtils.html>`_
+  This module implements operations for the built-in seq type
+  which were inspired by functional programming languages.
 
 
 String handling
@@ -250,6 +253,14 @@ Multimedia support
   the ``graphics`` module.
 
 
+Miscellaneous
+-------------
+
+* `events <events.html>`_
+  This module implements an event system that is not dependant on external
+  graphical toolkits.
+
+
 Database support
 ----------------
 
diff --git a/examples/allany.nim b/examples/allany.nim
index 4747ce0d6..8f84ba3fc 100755
--- a/examples/allany.nim
+++ b/examples/allany.nim
@@ -3,13 +3,22 @@
 template all(container, cond: expr): expr =
   block:
     var result = true
-    for item in items(container):
-      if not cond(item):
+    for it in items(container):
+      if not cond(it):
         result = false
         break
     result
 
-if all("mystring", {'a'..'z'}.contains): 
+template any(container, cond: expr): expr =
+  block:
+    var result = false
+    for it in items(container):
+      if cond(it):
+        result = true
+        break
+    result
+
+if all("mystring", {'a'..'z'}.contains) and any("myohmy", 'y'.`==`): 
   echo "works"
 else: 
   echo "does not work"
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
new file mode 100644
index 000000000..59d0d2658
--- /dev/null
+++ b/lib/pure/collections/sequtils.nim
@@ -0,0 +1,59 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2011 Alex Mitchell
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## :Author: Alex Mitchell
+##
+## This module implements operations for the built-in `seq`:idx: type
+## which were inspired by functional programming languages.
+
+proc concat*[T](seqs: openarray[seq[T]]): seq[T] =
+  ## Takes several sequences' items and returns them inside of one sequence.
+  var L = 0
+  for seqitm in items(seqs): inc(L, len(seqitm))
+  newSeq(result, L)
+  var i = 0
+  for s in items(seqs):
+    for itm in items(s):
+      result[i] = itm
+      inc(i)
+
+proc distnct*[T](seq1: seq[T]): seq[T] =
+  ## Removes duplicates from a sequence and returns it.
+  result = @[]
+  for itm in items(seq1):
+    if not result.contains(itm): result.add(itm)
+    
+proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
+  ## Combines two sequences. If one sequence is too short,
+  ## the remaining items in the longer sequence are discarded.
+  var m = min(seq1.len, seq2.len)
+  newSeq(result, m)
+  for i in 0 .. m-1: result[i] = (seq1[i], seq2[i])
+
+iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool): T =
+  ## Iterates through a sequence and yields every item that fulfills the
+  ## predicate.
+  for i in countup(0, len(seq1) -1):
+    var item = seq1[i]
+    if pred(item): yield seq1[i]
+
+proc filter*[T](seq1: seq[T], pred: proc(item: T): bool): seq[T] =
+  ## Returns all items in a sequence that fulfilled the predicate.
+  accumulateResult(filter(seq1, pred))
+
+template filterIt*(seq1, pred: expr): expr =
+  ## Finds a specific item in a sequence as long as the 
+  ## predicate returns true. The predicate needs to be an expression
+  ## containing ``it``: ``filterIt("abcxyz", it == 'x')``.
+  block:
+    var result: type(seq1) = @[]
+    for it in items(seq1):
+      if pred: result.add(it)
+    result
+
diff --git a/lib/pure/events.nim b/lib/pure/events.nim
new file mode 100644
index 000000000..00d6797d2
--- /dev/null
+++ b/lib/pure/events.nim
@@ -0,0 +1,83 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2011 Alex Mitchell
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## :Author: Alex Mitchell
+##
+## This module implements an event system that is not dependant on external
+## graphical toolkits. It was originally called ``NimEE`` because 
+## it was inspired by Ptyhon's PyEE module.
+
+type
+  TEventArgs* = object of TObject ## Base object for event arguments
+                                  ## that are passed to callback functions.
+  TEventHandler = tuple[name: string, handlers: seq[proc(e:TEventArgs)]]
+  PEventHandler* = ref TEventHandler ## An eventhandler for an event.
+
+type
+  TEventEmitter = object {.pure, final.}
+    s: seq[PEventHandler]
+  PEventEmitter* = ref TEventEmitter ## An object that fires events and 
+                                     ## holds event handlers for an object.
+  EInvalidEvent* = object of EInvalidValue
+    
+proc newEventHandler*(name: string): PEventHandler =
+  ## Initializes an EventHandler with the specified name and returns it.
+  new(result)
+  result.handlers = @[]
+  result.name = name
+
+proc addHandler*(handler: PEventHandler, func: proc(e: TEventArgs)) =
+  ## Adds the callback to the specified event handler.
+  handler.handlers.add(func)
+
+proc removeHandler*(handler: PEventHandler, func: proc(e: TEventArgs)) =
+  ## Removes the callback from the specified event handler.
+  for i in countup(0, len(handler.handlers) -1):
+    if func == handler.handlers[i]:
+      handler.handlers.del(i)
+      break
+    
+proc clearHandlers*(handler: PEventHandler) =
+  ## Clears all of the callbacks from the event handler.
+  setLen(handler.handlers, 0)
+
+proc getEventhandler(emitter: PEventEmitter, event: string): int =
+  for k in 0..high(emitter.s):
+    if emitter.s[k].name == event: return k
+  return -1
+
+proc on*(emitter: PEventEmitter, event: string, func: proc(e: TEventArgs)) =
+  ## Assigns a event handler with the specified callback. If the event
+  ## doesn't exist, it will be created.
+  var i = getEventHandler(emitter, event)
+  if i < 0:
+    var eh = newEventHandler(event)
+    addHandler(eh, func)
+    emitter.s.add(eh)
+  else:
+    addHandler(emitter.s[i], func)
+  
+proc emit*(emitter: PEventEmitter, eventhandler: PEventHandler, 
+           args: TEventArgs) =
+  ## Fires an event handler with specified event arguments.
+  for func in items(eventhandler.handlers): func(args)
+
+proc emit*(emitter: PEventEmitter, event: string, args: TEventArgs) =
+  ## Fires an event handler with specified event arguments.
+  var i = getEventHandler(emitter, event)
+  if i >= 0:
+    emit(emitter, emitter.s[i], args)
+  else:
+    raise newException(EInvalidEvent, "invalid event: " & event)
+
+proc newEventEmitter*(): PEventEmitter =
+  ## Creates and returns a new EventEmitter.
+  new(result)
+  result.s = @[]
+
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index cb4aaae54..d48e87ae2 100755
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -45,7 +45,9 @@ proc rawReadLine(f: TFile, result: var string) =
   setLen(result, 0) # reuse the buffer!
   while True:
     var c = fgetc(f)
-    if c < 0'i32: raiseEIO("EOF reached")
+    if c < 0'i32:
+      if result.len > 0: break
+      else: raiseEIO("EOF reached")
     if c == 10'i32: break # LF
     if c == 13'i32:  # CR
       c = fgetc(f) # is the next char LF?
@@ -89,19 +91,21 @@ proc readFile(filename: string): string =
         raiseEIO("error while reading from file")
     else:
       raiseEIO("file too big to fit in memory")
-  except EIO:
+  finally:
     close(f)
 
 proc writeFile(filename, content: string) =
   var f = open(filename, fmWrite)
-  f.write(content)
-  close(f)
+  try:
+    f.write(content)
+  finally:
+    close(f)
 
 proc EndOfFile(f: TFile): bool =
   # do not blame me; blame the ANSI C standard this is so brain-damaged
   var c = fgetc(f)
   ungetc(c, f)
-  return c == -1'i32
+  return c < 0'i32
 
 proc writeln[Ty](f: TFile, x: Ty) =
   write(f, x)
diff --git a/tests/accept/run/tevents.nim b/tests/accept/run/tevents.nim
new file mode 100644
index 000000000..2811c9625
--- /dev/null
+++ b/tests/accept/run/tevents.nim
@@ -0,0 +1,48 @@
+discard """
+file: "tevents.nim"
+output: '''HandlePrintEvent: Output -> Handled print event
+HandlePrintEvent2: Output -> printing for ME
+HandlePrintEvent2: Output -> printing for ME'''
+"""
+
+import events
+
+type
+  TPrintEventArgs = object of TEventArgs
+    user*: string
+
+proc handleprintevent*(e: TEventArgs) =
+    write(stdout, "HandlePrintEvent: Output -> Handled print event\n")
+        
+proc handleprintevent2*(e: TEventArgs) =
+    var args: TPrintEventArgs = TPrintEventArgs(e)
+    write(stdout, "HandlePrintEvent2: Output -> printing for " & args.user)
+    
+var ee = newEventEmitter()
+
+var eventargs: TPrintEventArgs
+eventargs.user = "ME\n"
+
+##method one test
+
+ee.on("print", handleprintevent)
+ee.on("print", handleprintevent2)
+
+ee.emit("print", eventargs)
+
+##method two test
+
+type
+  TSomeObject = object of TObject
+    PrintEvent: PEventHandler
+
+var obj: TSomeObject
+obj.PrintEvent = newEventHandler("print")
+obj.PrintEvent.addHandler(handleprintevent2)
+
+ee.emit(obj.PrintEvent, eventargs)
+
+obj.PrintEvent.removeHandler(handleprintevent2)
+
+ee.emit(obj.PrintEvent, eventargs)
+
diff --git a/tests/accept/run/tsequtils.nim b/tests/accept/run/tsequtils.nim
new file mode 100644
index 000000000..2982ca612
--- /dev/null
+++ b/tests/accept/run/tsequtils.nim
@@ -0,0 +1,55 @@
+discard """
+file: "tsequtils.nim"
+output: '''Zip: [{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}]
+Filter Iterator: 3
+Filter Iterator: 5
+Filter Iterator: 7
+Filter: [3, 5, 7]
+FilterIt: [1, 3, 7]
+Concat: [1, 3, 5, 7, 2, 4, 6]
+Distnct: [1, 2, 3, 4, 5, 7]'''
+
+"""
+
+import sequtils, marshal
+
+proc testFindWhere(item : int) : bool =
+  if item != 1: return true
+
+var seq1: seq[int] = @[]
+
+seq1.add(1)
+seq1.add(3)
+seq1.add(5)
+seq1.add(7)
+
+var seq2: seq[int] = @[2, 4, 6]
+var final = zip(seq1, seq2)
+
+echo "Zip: ", $$(final)
+
+#Test findWhere as a iterator
+
+for itms in filter(seq1, testFindWhere):
+  echo "Filter Iterator: ", $$(itms)
+
+
+#Test findWhere as a proc
+
+var fullseq: seq[int] = filter(seq1, testFindWhere)
+
+echo "Filter: ", $$(fullseq)
+
+#Test findIt as a template
+
+var finditval: seq[int] = filterIt(seq1, it!=5)
+
+echo "FilterIt: ", $$(finditval)
+
+var concatseq = concat(seq1,seq2)
+echo "Concat: ", $$(concatseq)
+
+var seq3 = @[1,2,3,4,5,5,5,7]
+var discntseq = distnct(seq3)
+echo "Distnct: ", $$(discntseq)
+
diff --git a/tools/nimgrep.nim b/tools/nimgrep.nim
index 3c9d769ea..4988222d5 100755
--- a/tools/nimgrep.nim
+++ b/tools/nimgrep.nim
@@ -107,8 +107,10 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int],
     stdout.write("\n")
 
 proc processFile(filename: string) = 
-  var buffer = system.readFile(filename)
-  if isNil(buffer): 
+  var buffer: string
+  try:
+    buffer = system.readFile(filename)
+  except EIO: 
     echo "cannot open file: ", filename
     return
   stdout.writeln(filename)
diff --git a/web/news.txt b/web/news.txt
index 51e8319d6..cb1da8773 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -13,6 +13,8 @@ Bugfixes
 - Boehm GC now works with ``--threads:on``.
 - Fixed a serious memory corruption concerning message passing.
 - Fixed a serious bug concerning different instantiations of a generic proc.
+- Fixed a newly introduced bug where a wrong ``EIO`` exception was raised for
+  the end of file for text files that do not end with a newline.
 
 
 Changes affecting backwards compatibility
diff --git a/web/nimrod.ini b/web/nimrod.ini
index 184fa01b1..b0c6d0139 100755
--- a/web/nimrod.ini
+++ b/web/nimrod.ini
@@ -41,6 +41,7 @@ srcdoc: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
 srcdoc: "impure/rdstdin;wrappers/zmq;wrappers/sphinx"
 srcdoc: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
 srcdoc: "pure/collections/intsets;pure/collections/queues;pure/encodings"
+srcdoc: "pure/lib/events;pure/collections/sequtils"
 
 webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
 webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"