[libgee] Add Iterator.stream method based on stream fusion



commit 0293f9520c8570ed1e1fc61eca5f8e4ef93b239a
Author: Maciej Piechotka <uzytkownik2 gmail com>
Date:   Sat Apr 30 11:39:42 2011 +0200

    Add Iterator.stream method based on stream fusion

 gee/iterator.vala |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 97 insertions(+), 0 deletions(-)
---
diff --git a/gee/iterator.vala b/gee/iterator.vala
index e9b4a73..91ced75 100644
--- a/gee/iterator.vala
+++ b/gee/iterator.vala
@@ -28,6 +28,7 @@ namespace Gee {
 	public delegate A FoldFunc<A, G> (owned G g, owned A a);
 	public delegate void ForallFunc<G> (owned G g);
 	public delegate Lazy<A>? UnfoldFunc<A> ();
+	public delegate Iterator.Stream StreamFunc<A, G> (Iterator.Stream state, owned G? g, out Lazy<A>? lazy);
 }
 
 /**
@@ -113,6 +114,102 @@ public interface Gee.Iterator<G> : Object {
 			f (get ());
 	}
 
+
+	/**
+	 * Stream function is an abstract function allowing writing many
+	 * operations.
+	 *
+	 * The stream function accepts three parameter:
+	 *
+	 *   1. state. It is usually the last returned value from function but
+	 *      it may be Stream.END when the previous value was Stream.CONTINUE
+	 *      and threre was no next element.
+	 *   2. input. It is valid only if first argument is Stream.CONTINUE
+	 *   3. output. It is valid only if result is Stream.YIELD
+	 *
+	 * It may return one of 3 results:
+	 *
+	 *   1. Stream.YIELD. It means that value was yielded and can be passed
+	 *      to outgoint iterator
+	 *   2. Stream.CONTINUE. It means that the function needs to be rerun
+	 *      with next element (or Stream.END if it is end of stream). If
+	 *      the state argument is Stream.END the function MUST NOT return
+	 *      this value.
+	 *   3. Stream.END. It means that the last argument was yielded.
+	 *
+	 * If the function yields the value immidiatly then the returning iterator
+	 * is { link valid} and points to this value as well as in case when the
+	 * parent iterator is { link valid} and function yields after consuming
+	 * 1 input. In other case returned iterator is invalid.
+	 *
+	 * Usage of the parent is invalid before the { link next} or
+	 * { link has_next} returns false and the value will be force-evaluated.
+	 *
+	 * @param f function generating stream
+	 * @return iterator containing values yielded by stream
+	 */
+	public virtual Iterator<A> stream<A> (owned StreamFunc<A, G> f_) {
+		Stream str;
+		Lazy<A>? initial = null;
+		bool need_next = true;
+		StreamFunc<A, G> f = (owned)f_;
+		str = f (Stream.YIELD, null, out initial);
+		switch (str) {
+		case Stream.CONTINUE:
+			if (valid) {
+				str = f (Stream.CONTINUE, get (), out initial);
+				switch (str) {
+				case Stream.YIELD:
+				case Stream.CONTINUE:
+					break;
+				case Stream.END:
+					return unfold<A> (() => {return null;});
+				default:
+					assert_not_reached ();
+				}
+			}
+			break;
+		case Stream.YIELD:
+			if (valid)
+				need_next = false;
+			break;
+		case Stream.END:
+			return unfold<A> (() => {return null;});
+		default:
+			assert_not_reached ();
+		}
+		return unfold<A> (() => {
+			Lazy<A>? val;
+			str = f (Stream.YIELD, null, out val);
+			while (str == Stream.CONTINUE) {
+				if (need_next) {
+					if (!next ()) {
+						str = f (Stream.END, null, out val);
+						assert (str != Stream.CONTINUE);
+						break;
+					}
+				} else {
+					need_next = true;
+				}
+				str = f (Stream.CONTINUE, get (), out val);
+			}
+			switch (str) {
+			case Stream.YIELD:
+				return val;
+			case Stream.END:
+				return null;
+			default:
+				assert_not_reached ();
+			}
+		}, initial);
+	}
+
+	public enum Stream {
+		YIELD,
+		CONTINUE,
+		END
+	}
+
 	/**
 	 * Create iterator from unfolding function. The lazy value is
          * force-evaluated before progressing to next element.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]