Эх сурвалжийг харах

Refactor iteration method

Billy Barrow 3 жил өмнө
parent
commit
13154b337e

+ 20 - 7
src/lib/Concrete/ArrayEnumerable.vala

@@ -10,13 +10,26 @@ namespace Invercargill {
             array = input;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-            foreach (var item in array) {
-                if(!handler(item)) {
-                    break;
-                }
-            }
-            return true;
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //      foreach (var item in array) {
+        //          if(!handler(item)) {
+        //              break;
+        //          }
+        //      }
+        //      return true;
+        //  }
+
+        public override Tracker<T> to_tracker() {
+            var i = 0;
+            return new LambdaTracker<T>(
+                () => {
+                    return i < array.length;
+                },
+                () => {
+                    var res = array[i];
+                    i++;
+                    return res;
+                });
         }
 
     }

+ 19 - 5
src/lib/Concrete/ConcatEnumerable.vala

@@ -11,11 +11,25 @@ namespace Invercargill {
             e2 = second;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-            if(e1.iterate_if (handler)) {
-                return e2.iterate_if (handler);
-            }
-            return false;
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //      if(e1.iterate_if (handler)) {
+        //          return e2.iterate_if (handler);
+        //      }
+        //      return false;
+        //  }
+
+        public override Tracker<T> to_tracker() {
+            var tracker1 = e1.to_tracker();
+            var tracker2 = e2.to_tracker();
+
+            return new LambdaTracker<T>(
+                () => tracker1.has_next() || tracker2.has_next(),
+                () => {
+                    if(tracker1.has_next()) {
+                        return tracker1.get_next();
+                    }
+                    return tracker2.get_next();
+                });
         }
 
     }

+ 28 - 12
src/lib/Concrete/DirEnumerable.vala

@@ -3,22 +3,38 @@ namespace Invercargill {
 
     internal class DirEnumerable : Enumerable<string> {
 
-        private Dir dir;
+        private string path;
+        private uint flags;
 
-        public DirEnumerable(owned Dir dir) {
-            this.dir = (owned)dir;
+        public DirEnumerable(string path, uint flags = 0) {
+            this.path = path;
+            this.flags = flags;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-            string? name = null;
-            while ((name = dir.read_name ()) != null) {
-                if(!handler(name)) {
-                    dir.rewind();
-                    return false;
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //      string? name = null;
+        //      while ((name = dir.read_name ()) != null) {
+        //          if(!handler(name)) {
+        //              dir.rewind();
+        //              return false;
+        //          }
+        //      }
+        //      dir.rewind();
+        //      return true;
+        //  }
+
+        public override Tracker<string> to_tracker() {
+            var dir = Dir.open(path, flags);
+
+            return new AdvanceTracker<string>((out obj) => {
+                var name = dir.read_name();
+                if(name != null) {
+                    obj = name;
+                    return true;
                 }
-            }
-            dir.rewind();
-            return true;
+                obj = null;
+                return false;
+            });
         }
 
     }

+ 19 - 7
src/lib/Concrete/GeeEnumerable.vala

@@ -11,13 +11,25 @@ namespace Invercargill {
             iterable = gee;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-            foreach(var item in iterable) {
-                if(!handler(item)) {
-                    return false;
-                }
-            }
-            return true;
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //      foreach(var item in iterable) {
+        //          if(!handler(item)) {
+        //              return false;
+        //          }
+        //      }
+        //      return true;
+        //  }
+
+        
+        public override Tracker<T> to_tracker() {
+            var iterator = iterable.iterator();
+
+            return new LambdaTracker<T>(
+                () => iterator.has_next(),
+                () => {
+                    iterator.next();
+                    return iterator.get();
+                });
         }
 
     }

+ 33 - 0
src/lib/Concrete/IterableEnumerable.vala

@@ -0,0 +1,33 @@
+
+//  using Gee;
+
+//  namespace Invercargill {
+
+//      private class IterableEnumerable<T> : Enumerable<T>, Iterable<T>, Object, Traversable<T> {
+
+//          private Iterable<T> iterable;
+
+//          public GeeEnumerable(Iterable<T> gee) {
+//              iterable = gee;
+//          }
+        
+//          public override Tracker<T> to_tracker() {
+//              var iterator = iterable.iterator();
+
+//              return new LambdaTracker<T>(
+//                  () => iterator.has_next(),
+//                  () => {
+//                      iterator.next();
+//                      return iterator.get();
+//                  });
+//          }
+//      public Gee.Iterator<T> iterator () {
+//          assert_not_reached ();
+//      }
+//      public new bool foreach (Gee.ForallFunc<T> f) {
+//          assert_not_reached ();
+//      }
+
+//      }
+
+//  }

+ 20 - 16
src/lib/Concrete/PairEnumerable.vala

@@ -2,25 +2,29 @@ namespace Invercargill {
 
     public class PairEnumerable<T1, T2> : Enumerable<Pair<T1, T2>> {
 
-        private Sequence<T1> s1;
-        private Sequence<T2> s2;
+        private Enumerable<T1> e1;
+        private Enumerable<T2> e2;
 
-        public PairEnumerable(Sequence<T1> seq1, Sequence<T2> seq2) {
-            s1 = seq1;
-            s2 = seq2;
+        public PairEnumerable(Enumerable<T1> en1, Enumerable<T2> en2) {
+            e1 = en1;
+            e2 = en2;
         }
 
-        public override bool iterate_if (PredicateDelegate<T> handler) {
-            var current1 = s1.root;
-            var current2 = s2.root;
-            while(current1 != null || current2 != null) {
-                if(!handler(new Pair<T1, T2>(current1?.value, current1 != null, current2?.value, current2 != null))) {
-                    return false;
-                }
-                current1 = current1?.next;
-                current2 = current2?.next;
-            }
-            return true;
+        public override Tracker<Pair<T1, T2>> to_tracker() {
+            var tracker1 = e1.to_tracker();
+            var tracker2 = e2.to_tracker();
+
+            return new LambdaTracker<Pair<T1, T2>>(
+                () => tracker1.has_next() || tracker2.has_next(),
+                () => {
+                    var t1vs = tracker1.has_next();
+                    var t2vs = tracker2.has_next();
+                    return new Pair<T1, T2>(
+                        t1vs ? tracker1.get_next() : null,
+                        t1vs,
+                        t2vs ? tracker2.get_next() : null,
+                        t2vs);
+                });
         }
 
     }

+ 19 - 7
src/lib/Concrete/RangeEnumerable.vala

@@ -13,13 +13,25 @@ namespace Invercargill {
             this.stride = stride;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<int> handler) {
-            for(int i = start; i < stop; i += stride) {
-                if(!handler(i)) {
-                    return false;
-                }
-            }
-            return true;
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<int> handler) {
+        //      for(int i = start; i < stop; i += stride) {
+        //          if(!handler(i)) {
+        //              return false;
+        //          }
+        //      }
+        //      return true;
+        //  }
+
+        public override Tracker<int> to_tracker() {
+            var i = start;
+
+            return new LambdaTracker<int>(
+                () => i < stop,
+                () => {
+                    var val = i;
+                    i++;
+                    return val;
+                });
         }
 
     }

+ 20 - 8
src/lib/Concrete/Sequence.vala

@@ -17,15 +17,27 @@ namespace Invercargill {
 
         public Sequence() {}
 
-        public override bool iterate_if (PredicateDelegate<T> handler) {
+        //  public override bool iterate_if (PredicateDelegate<T> handler) {
+        //      var current = root;
+        //      while(current != null) {
+        //          if(!handler(current.value)) {
+        //              return false;
+        //          }
+        //          current = current.next;
+        //      }
+        //      return true;
+        //  }
+
+        public override Tracker<T> to_tracker() {
             var current = root;
-            while(current != null) {
-                if(!handler(current.value)) {
-                    return false;
-                }
-                current = current.next;
-            }
-            return true;
+
+            return new LambdaTracker<T>(
+                () => current != null,
+                () => {
+                    var val = current.value;
+                    current = current.next;
+                    return val;
+                });
         }
 
         public override T[] to_array () {

+ 42 - 13
src/lib/Concrete/ZipperEnumerable.vala

@@ -2,22 +2,51 @@ namespace Invercargill {
 
     public class ZipperEnumerable<T> : Enumerable<T> {
 
-        private Enumerable<Pair<T, T>> inputs;
+        private Enumerable<T> e1;
+        private Enumerable<T> e2;
 
-        public ZipperEnumerable(Enumerable<T> seq1, Enumerable<T> seq2) {
-            inputs = seq1.pair<T>(seq2);
+        public ZipperEnumerable(Enumerable<T> en1, Enumerable<T> en2) {
+            e1 = en1;
+            e2 = en2;
         }
 
-        public override bool iterate_if (PredicateDelegate<T> handler) {
-            return inputs.iterate_if (i => {
-                if(i.value1_is_set) {
-                    if(!handler(i.value1)) { return false; }
-                }
-                if(i.value2_is_set) {
-                    if(!handler(i.value2)) { return false; }
-                }
-                return true;
-            });
+        //  public override bool iterate_if (PredicateDelegate<T> handler) {
+        //      return inputs.iterate_if (i => {
+        //          if(i.value1_is_set) {
+        //              if(!handler(i.value1)) { return false; }
+        //          }
+        //          if(i.value2_is_set) {
+        //              if(!handler(i.value2)) { return false; }
+        //          }
+        //          return true;
+        //      });
+        //  }
+
+        public override Tracker<T> to_tracker() {
+            var t1 = e1.to_tracker();
+            var t2 = e2.to_tracker();
+            var last = t2;
+
+            return new LambdaTracker<T>(
+                () => t1.has_next() || t2.has_next(),
+                () => {
+                    if(last == t1 && t2.has_next()) {
+                        last = t2;
+                        return t2.get_next();
+                    }
+                    else if(last == t2 && t1.has_next()) {
+                        last = t1;
+                        return t1.get_next();
+                    }
+                    else if(t1.has_next()) {
+                        last = t1;
+                        return t1.get_next();
+                    }
+                    else {
+                        last = t2;
+                        return t2.get_next();
+                    }
+                });
         }
 
     }

+ 27 - 13
src/lib/Enumerable.vala

@@ -1,11 +1,25 @@
 
 namespace Invercargill {
 
+    //  public interface Enumerable<T> {
+        
+    //  }
+
     public abstract class Enumerable<T> {
 
+        public abstract Tracker<T> to_tracker();
+
         // Returns false if iteration was interrupted
         // Returns true if iteration reached natural end
-        public abstract bool iterate_if(PredicateDelegate<T> handler);
+        public virtual bool iterate_if(PredicateDelegate<T> handler) {
+            var tracker = to_tracker();
+            while(tracker.has_next()) {
+                if(!handler(tracker.get_next())) {
+                    return false;
+                }
+            }
+            return true;
+        }
 
         public virtual void iterate(ItemDelegate<T> handler) {
             iterate_if(i => {
@@ -57,20 +71,20 @@ namespace Invercargill {
             return all(i => !predicate(i));
         }
 
-        public virtual Enumerable<T> where(PredicateDelegate<T> predicate) {
-            return new FilterQuery<T>(this, predicate);
+        public virtual Enumerable<T> where(owned PredicateDelegate<T> predicate) {
+            return new FilterQuery<T>(this, (owned)predicate);
         }
 
-        public virtual Enumerable<Tout> select<Tout>(TransformDelegate<T, Tout> transform) {
-            return new TransformQuery<T, Tout>(this, transform);
+        public virtual Enumerable<Tout> select<Tout>(owned TransformDelegate<T, Tout> transform) {
+            return new TransformQuery<T, Tout>(this, (owned)transform);
         }
 
-        public virtual Enumerable<Tout> select_many<Tout>(TransformDelegate<T, Enumerable<Tout>> transform) {
-            return new MergeQuery<Tout>(select(transform));
+        public virtual Enumerable<Tout> select_many<Tout>(owned TransformDelegate<T, Enumerable<Tout>> transform) {
+            return new MergeQuery<Tout>(select((owned)transform));
         }
 
-        public virtual Enumerable<T> sort(CompareDelegate<T> compare) {
-            return new SortQuery<T>(this, compare);
+        public virtual Enumerable<T> sort(owned CompareDelegate<T> compare) {
+            return new SortQuery<T>(this, (owned)compare);
         }
 
         public virtual Enumerable<T> concat(Enumerable<T> other) {
@@ -105,13 +119,13 @@ namespace Invercargill {
             return new ZipperEnumerable<T>(this, other);
         }
 
-        public virtual Enumerable<Tout> fork<Tout>(TransformDelegate<T, Tout> fork1, TransformDelegate<T, Tout> fork2) {
+        public virtual Enumerable<Tout> fork<Tout>(owned TransformDelegate<T, Tout> fork1, owned TransformDelegate<T, Tout> fork2) {
             var seq = to_sequence();
-            return seq.select<Tout>(fork1).zip(seq.select<Tout>(fork2));
+            return seq.select<Tout>((owned)fork1).zip(seq.select<Tout>((owned)fork2));
         }
 
-        public virtual Enumerable<Tout> fork_many<Tout>(TransformDelegate<T, Enumerable<Tout>> fork1, TransformDelegate<T, Enumerable<Tout>> fork2) {
-            return new MergeQuery<Tout>(fork(fork1, fork2));
+        public virtual Enumerable<Tout> fork_many<Tout>(owned TransformDelegate<T, Enumerable<Tout>> fork1, owned TransformDelegate<T, Enumerable<Tout>> fork2) {
+            return new MergeQuery<Tout>(fork((owned)fork1, (owned)fork2));
         }
 
         public virtual bool matches(Enumerable<T> other, EqualityDelegate<T> equals) {

+ 3 - 3
src/lib/Invercargill.vala

@@ -16,9 +16,9 @@ namespace Invercargill {
         return new GeeEnumerable<T>(input);
     }
 
-    public static Enumerable<string> dte(owned Dir input) {
-        return new DirEnumerable((owned)input);
-    }
+    //  public static Enumerable<string> dte(path input) {
+    //      return new DirEnumerable(input);
+    //  }
 
     public static Enumerable<int> range(int count, int start = 0, int increment = 1) {
         return new RangeEnumerable(start, count, increment);

+ 24 - 8
src/lib/Queries/Filter.vala

@@ -3,19 +3,35 @@ namespace Invercargill {
     private class FilterQuery<T> : BaseQuery<T, T> {
         private PredicateDelegate<T> predicate_func;
 
-        public FilterQuery(Enumerable<T> input, PredicateDelegate<T> func) {
+        public FilterQuery(Enumerable<T> input, owned PredicateDelegate<T> func) {
             this.input = input;
-            predicate_func = x => func(x);
+            predicate_func = (owned)func;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-            return input.iterate_if(i => {
-                if(predicate_func(i)) {
-                    if(!handler(i)) {
-                        return false;
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //      return input.iterate_if(i => {
+        //          if(predicate_func(i)) {
+        //              if(!handler(i)) {
+        //                  return false;
+        //              }
+        //          }
+        //          return true;
+        //      });
+        //  }
+
+        public override Tracker<T> to_tracker() {
+            var tracker = input.to_tracker();
+
+            return new AdvanceTracker<T>((out obj) => {
+                while(tracker.has_next()) {
+                    var item = tracker.get_next();
+                    if(predicate_func(item)){
+                        obj = item;
+                        return true;
                     }
                 }
-                return true;
+                obj = null;
+                return false;
             });
         }
     }

+ 17 - 0
src/lib/Queries/Merge.vala

@@ -10,6 +10,23 @@ namespace Invercargill {
             return input.iterate_if(i => i.iterate_if(handler));
         }
 
+        public override Tracker<T> to_tracker() {
+            var outer_tracker = input.to_tracker();
+            Tracker<T> inner_tracker = null;
+
+            return new AdvanceTracker<T>((out obj) => {
+                while(inner_tracker == null || !inner_tracker.has_next()) {
+                    if(!outer_tracker.has_next()) {
+                        obj = null;
+                        return false;
+                    }
+                    inner_tracker = outer_tracker.get_next().to_tracker();
+                }
+                obj = inner_tracker.get_next();
+                return true;
+            });
+        }
+
     }
 
 }

+ 21 - 0
src/lib/Queries/Skip.vala

@@ -20,6 +20,27 @@ namespace Invercargill {
                 return true;
             });
         }
+
+        public override Tracker<T> to_tracker() {
+            var tracker = input.to_tracker();
+            var c = 0;
+
+            return new AdvanceTracker<T>((out obj) => {
+                obj = null;
+                while(c < n_items) {
+                    if(!tracker.has_next()) {
+                        return false;
+                    }
+                    c++;
+                }
+                
+                if(tracker.has_next()) {
+                    obj = tracker.get_next();
+                    return true;
+                }
+                return false;
+            });
+        }
     }
 
 }

+ 15 - 8
src/lib/Queries/Sort.vala

@@ -3,17 +3,17 @@ namespace Invercargill {
     private class SortQuery<T> : BaseQuery<T, T> {
         private CompareDelegate<T> compare_func;
 
-        public SortQuery(Enumerable<T> input, CompareDelegate<T> compare) {
+        public SortQuery(Enumerable<T> input, owned CompareDelegate<T> compare) {
             this.input = input;
-            compare_func = (a, b) => compare(a, b);
+            compare_func = (owned)compare;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-            // Hack for now
-            var list = to_collection();
-            list.order_by ((a, b) => compare_func(a, b));
-            return gte<T>(list).iterate_if(handler);
-        }
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //      // Hack for now
+        //      var list = to_collection();
+        //      list.order_by ((a, b) => compare_func(a, b));
+        //      return gte<T>(list).iterate_if(handler);
+        //  }
 
         private class SortItem<T> {
             public CompareDelegate<T> compare_func;
@@ -24,6 +24,13 @@ namespace Invercargill {
                 compare_func = (a, b) => func(a, b);
             }
         }
+
+        public override Tracker<T> to_tracker() {
+            // Hack for now
+            var list = to_collection();
+            list.order_by ((a, b) => compare_func(a, b));
+            return gte<T>(list).to_tracker();
+        }
     }
 
 }

+ 24 - 6
src/lib/Queries/Take.vala

@@ -9,15 +9,33 @@ namespace Invercargill {
             n_items = count;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
+        //      var c = 0;
+        //      return input.iterate_if(i => {
+        //          if(c < n_items) {
+        //              c++;
+        //              return handler(i);
+        //          }
+        //          return false;             
+        //      });
+        //  }
+
+        public override Tracker<T> to_tracker() {
+            var tracker = input.to_tracker();
             var c = 0;
-            return input.iterate_if(i => {
-                if(c < n_items) {
+
+            return new LambdaTracker<T>(
+                () => {
+                    if(c < n_items) {
+                        return tracker.has_next();
+                    }
+                    return false;
+                },
+                () => {
                     c++;
-                    return handler(i);
+                    return tracker.get_next();
                 }
-                return false;             
-            });
+            );
         }
     }
 

+ 12 - 4
src/lib/Queries/Transform.vala

@@ -3,13 +3,21 @@ namespace Invercargill {
     private class TransformQuery<Tin, Tout> : BaseQuery<Tin, Tout> {
         private TransformDelegate<Tin, Tout> transform_func;
 
-        public TransformQuery(Enumerable<Tin> input, TransformDelegate<Tin, Tout> transform) {
+        public TransformQuery(Enumerable<Tin> input, owned TransformDelegate<Tin, Tout> transform) {
             this.input = input;
-            transform_func = x => transform(x);
+            transform_func = (owned)transform;
         }
 
-        public override bool iterate_if (Invercargill.PredicateDelegate<Tout> handler) {
-            return input.iterate_if(i => handler(transform_func(i)));
+        //  public override bool iterate_if (Invercargill.PredicateDelegate<Tout> handler) {
+        //      return input.iterate_if(i => handler(transform_func(i)));
+        //  }
+
+        public override Tracker<Tout> to_tracker() {
+            var tracker = input.to_tracker();
+            return new LambdaTracker<Tout>(
+                () => tracker.has_next(),
+                () => transform_func(tracker.get_next())
+            );
         }
     }
 

+ 53 - 0
src/lib/Tracker.vala

@@ -0,0 +1,53 @@
+namespace Invercargill {
+
+    public abstract class Tracker<T> {
+
+        public abstract bool has_next();
+        public abstract T get_next();
+
+    }
+
+    public class AdvanceTracker<T> : Tracker<T> {
+        public delegate bool GetNextDelegate<T>(out T? item);
+
+        private GetNextDelegate<T> get_next_func;
+        private bool has_next_item;
+        private T? next_item;
+
+        public AdvanceTracker(owned GetNextDelegate<T> get_next_delegate) {
+            get_next_func = (owned)get_next_delegate;
+            has_next_item = get_next_func(out next_item);
+        }
+
+        public override bool has_next () {
+            return has_next_item;
+        }
+        public override T get_next () {
+            var item = next_item;
+            has_next_item = get_next_func(out next_item);
+            return item;
+        }
+    }
+
+    public class LambdaTracker<T> : Tracker<T> {
+        public delegate bool HasNextDelegate();
+        public delegate T GetNextDelegate<T>();
+
+        private HasNextDelegate has_next_func;
+        private GetNextDelegate get_next_func;
+
+        public LambdaTracker(owned HasNextDelegate has_next_delegate, owned GetNextDelegate<T> get_next_delegate) {
+            has_next_func = (owned)has_next_delegate;
+            get_next_func = (owned)get_next_delegate;
+        }
+
+        public override bool has_next () {
+            return has_next_func();
+        }
+        public override T get_next () {
+            return get_next_func();
+        }
+
+    }
+
+}

+ 2 - 0
src/lib/meson.build

@@ -10,6 +10,7 @@ sources = files('Invercargill.vala')
 sources += files('Enumerable.vala')
 sources += files('Delegates.vala')
 sources += files('Pair.vala')
+sources += files('Tracker.vala')
 
 sources += files('Queries/Query.vala')
 sources += files('Queries/Transform.vala')
@@ -28,6 +29,7 @@ sources += files('Concrete/PairEnumerable.vala')
 sources += files('Concrete/DirEnumerable.vala')
 sources += files('Concrete/ZipperEnumerable.vala')
 sources += files('Concrete/Sequence.vala')
+sources += files('Concrete/IterableEnumerable.vala')
 
 invercargill = shared_library('invercargill', sources,
     dependencies: dependencies,

+ 3 - 1
src/tests/Integration/Where.vala

@@ -8,7 +8,9 @@ void where_tests() {
 
         var result = items.where(i => true);
         
-        assert_true(expected.matches(result, (a, b) => a == b));
+        assert_true(expected.matches(result, (a, b) => {
+            return a == b;
+        }));
     });
 
     Test.add_func("/invercargill/operator/where/all-false", () => {