added functionality to list and iter packages
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 26 Nov 2021 15:38:32 +0000 (09:38 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 26 Nov 2021 15:38:32 +0000 (09:38 -0600)
core/container/iter.onyx
core/container/list.onyx

index 4a52400f0b5d5dfa280afb262049c7217b769882..698b40bb6a89f4f6eaf5e4851ba910cbf9691d65 100644 (file)
@@ -287,23 +287,6 @@ enumerate :: #match {}
     };
 }
 
-fold :: (it: Iterator($T), initial_value: R, combine: (T, $R) -> R) -> R {
-    for value: it {
-        initial_value = combine(value, initial_value);
-    }
-    
-    return initial_value;
-}
-
-to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
-    array :: package core.array
-
-    arr := array.make(T, allocator=allocator);
-    for v: it do array.push(^arr, v);
-
-    return arr;
-}
-
 #match as_iterator from_array
 from_array :: (arr: [] $T) -> Iterator(^T) {
     Context :: struct (T: type_expr) {
@@ -377,3 +360,61 @@ from_array :: (arr: [] $T) -> Iterator(^T) {
         close = close,
     };
 }
+
+fold :: #match {}
+@Cleanup // some way to shorten this would be nice
+#match fold macro (it: $T, init: $R, combine: $S) -> #auto where Iterable(T) {
+    fold :: fold
+    return fold(it, init, combine);
+}
+
+#match fold (it: Iterator($T), initial_value: R, combine: (T, $R) -> R) -> R {
+    for value: it {
+        initial_value = combine(value, initial_value);
+    }
+    
+    return initial_value;
+}
+
+count :: #match {}
+#match count macro (it: $T, cond: $F) -> #auto where Iterable(T) {
+    count :: count
+    return count(it, cond);
+}
+
+#match count (it: Iterator($T), cond: (T) -> bool) -> i32 {
+    c := 0;
+    for value: it do if cond(value) do c += 1;
+    return c;
+}
+
+some :: #match {}
+#match some macro (it: $T, cond: $F) -> #auto where Iterable(T) {
+    some :: some
+    return some(it, cond);
+}
+
+#match some (it: Iterator($T), cond: (T) -> bool) -> bool {
+    for value: it do if cond(value) do return true;
+    return false;
+}
+
+every :: #match {}
+#match every macro (it: $T, cond: $F) -> #auto where Iterable(T) {
+    every :: every
+    return every(it, cond);
+}
+
+#match every (it: Iterator($T), cond: (T) -> bool) -> bool {
+    for value: it do if !cond(value) do return false;
+    return true;
+}
+
+to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
+    array :: package core.array
+
+    arr := array.make(T, allocator=allocator);
+    for v: it do array.push(^arr, v);
+
+    return arr;
+}
index 04c82d9315165da4f14816e89e8803a373ff02bb..9d8ee581797103ed58690a7ea6a2ed32364634f0 100644 (file)
@@ -13,12 +13,34 @@ List :: struct (T: type_expr) {
 
     first: ^ListElem(T) = null;
     last:  ^ListElem(T) = null;
+
+    // "Method" like things
+    free         :: free
+    push_end     :: push_end
+    push_begin   :: push_begin
+    pop_end      :: pop_end
+    pop_begin    :: pop_begin
+    count        :: count
+    at           :: at
+    contains     :: contains
+    fold         :: fold
+    map          :: map
+    get_iterator :: get_iterator
 }
 
 make :: ($T: type_expr, allocator := context.allocator) -> List(T) {
     return .{ allocator = allocator };
 }
 
+free :: (list: ^List($T)) {
+    elem := list.first;
+    while elem != null {
+        to_delete := elem;
+        elem = elem.next;
+        raw_free(list.allocator, elem);
+    }
+}
+
 push_end :: (list: ^List($T), x: T) { 
     new_elem := allocate_elem(list);
     new_elem.data = x;
@@ -63,6 +85,28 @@ pop_begin :: (list: ^List($T), default: T = __zero_value(T)) -> T {
     return begin.data;
 }
 
+count :: (list: ^List($T)) -> i32 {
+    c := 0;
+    elem := list.first;
+    while elem != null {
+        c += 1;
+        elem = elem.next;
+    }
+
+    return c;
+}
+
+at :: (list: ^List($T), index: i32) -> ^T {
+    elem := list.first;
+    while elem != null {
+        if index == 0 do return ^elem.data;
+        index -= 1;
+        elem = elem.next;
+    }
+
+    return null;
+}
+
 contains :: (list: ^List($T), x: T) -> bool {
     elem := list.first;
     while elem != null {
@@ -85,11 +129,26 @@ fold :: (list: ^List($T), init: $R, f: (T, R) -> R) -> R {
     return val;
 }
 
-// map :: #match {
-//     (list: ^List($T), f: (^T) -> void) {
-//     }
-// }
+map :: #match {}
+#match map (list: ^List($T), f: (^T) -> void) {
+    elem := list.first;
+    while elem != null {
+        f(^elem.data);
+        elem = elem.next;
+    }
+}
+
+#match map (list: ^List($T), f: (T) -> $R) -> List(R) {
+    new_list := make(R, allocator=list.allocator);
+    elem := list.first;
+    while elem != null {
+        push_end(new_list, f(elem.data));
+        elem = elem.next;
+    }
+}
 
+#local iter :: package core.iter
+#match iter.as_iterator get_iterator
 get_iterator :: (list: ^List($T)) -> Iterator(T) {
     iterator_next :: (list_iter: ^ListIterator($T)) -> (T, bool) {
         use package core.intrinsics.onyx { __zero_value }
@@ -113,5 +172,4 @@ get_iterator :: (list: ^List($T)) -> Iterator(T) {
     };
 }
 
-#local
-allocate_elem :: macro (list: ^List($T)) => new(ListElem(T), allocator=list.allocator);
+#local allocate_elem :: macro (list: ^List($T)) => new(ListElem(T), allocator=list.allocator);