bugfixes in standard library; added iter.skip_while
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 8 Dec 2022 16:36:19 +0000 (10:36 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 8 Dec 2022 16:36:19 +0000 (10:36 -0600)
core/alloc/gc.onyx
core/container/array.onyx
core/container/iter.onyx
core/string/string.onyx

index ac44b7b4524b02a9bdc30eac9160a9d2685f1e77..83eba584907f1fa7498b05b770244d77a22b1528 100644 (file)
@@ -52,10 +52,8 @@ auto :: #match {
     macro (body: Code) -> i32 {
         auto :: auto
 
-        #context_scope {
-            auto(); 
-            #unquote body;
-        }
+        auto(); 
+        #unquote body;
 
         return 0;
     }
index be954731483213aa66dca02b3d042f06865398e5..051075c63505e15fc9502b9b46340511004b71b2 100644 (file)
@@ -339,11 +339,13 @@ reverse :: (arr: [] $T) {
 //
 // Simple insertion sort
 //    cmp should return >0 if left > right
+// Returns the array to be used in '|>' chaining.
+// NOT A COPY OF THE ARRAY.
 //
 sort :: #match #local {}
 
 #overload
-sort :: (arr: [] $T, cmp: (T, T) -> i32) {
+sort :: (arr: [] $T, cmp: (T, T) -> i32) -> [] T {
     for i: 1 .. arr.count {
         x := arr.data[i];
         j := i - 1;
@@ -360,10 +362,12 @@ sort :: (arr: [] $T, cmp: (T, T) -> i32) {
 
         arr.data[j + 1] = x;
     }
+
+    return arr;
 }
 
 #overload
-sort :: (arr: [] $T, cmp: (^T, ^T) -> i32) {
+sort :: (arr: [] $T, cmp: (^T, ^T) -> i32) -> [] T {
     for i: 1 .. arr.count {
         j := i;
 
@@ -376,11 +380,13 @@ sort :: (arr: [] $T, cmp: (^T, ^T) -> i32) {
             }
         }
     }
+
+    return arr;
 }
 
 quicksort :: #match #locked {
-    (arr: [] $T, cmp: ( T,  T) -> i32) do quicksort_impl(arr, cmp, 0, arr.count - 1); ,
-    (arr: [] $T, cmp: (^T, ^T) -> i32) do quicksort_impl(arr, cmp, 0, arr.count - 1); ,
+    (arr: [] $T, cmp: ( T,  T) -> i32) => { quicksort_impl(arr, cmp, 0, arr.count - 1); return arr; },
+    (arr: [] $T, cmp: (^T, ^T) -> i32) => { quicksort_impl(arr, cmp, 0, arr.count - 1); return arr; },
 }
 
 #local {
index 77f7bc38e1d2770a90333542b8fbf34662338788..d3e3fcabdf9ebbec1bf0aea612f778eb6aadd638 100644 (file)
@@ -313,6 +313,98 @@ skip :: (it: Iterator($T), count: u32, allocator := context.temp_allocator) -> I
     };
 }
 
+skip_while :: #match #local {}
+
+#overload
+skip_while :: (it: Iterator($T), predicate: (T) -> bool, allocator := context.temp_allocator) -> Iterator(T) {
+    SkipIterator :: struct (T: type_expr) {
+        iterator: Iterator(T);
+        allocator: Allocator;
+        predicate: (T) -> bool;
+        skipped := false;
+    }
+
+    skip_iterator := new(SkipIterator(T), allocator=allocator);
+    skip_iterator.iterator = it;
+    skip_iterator.allocator = allocator;
+    skip_iterator.predicate = predicate;
+
+    next :: (si: ^SkipIterator($T)) -> (T, bool) {
+        while !si.skipped {
+            value, cont := si.iterator.next(si.iterator.data);
+
+            if !cont {
+                si.skipped = true;
+                return value, false;
+            }
+
+            if !si.predicate(value) {
+                si.skipped = true;
+                return value, true;
+            }
+        }
+
+        return si.iterator.next(si.iterator.data);
+    }
+
+    close :: (si: ^SkipIterator($T)) {
+        if si.iterator.close != null_proc do si.iterator.close(si.iterator.data);
+        raw_free(si.allocator, si);
+    }
+
+    return .{
+        data  = skip_iterator,
+        next  = #solidify next  { T=T },
+        close = #solidify close { T=T },
+    };
+}
+
+#overload
+skip_while :: (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool, allocator := context.temp_allocator) -> Iterator(T) {
+    SkipIterator :: struct (T: type_expr, Ctx: type_expr) {
+        iterator: Iterator(T);
+        allocator: Allocator;
+        predicate: (T, Ctx) -> bool;
+        ctx: Ctx;
+        skipped := false;
+    }
+
+    skip_iterator := new(SkipIterator(T, Ctx), allocator=allocator);
+    skip_iterator.iterator = it;
+    skip_iterator.allocator = allocator;
+    skip_iterator.predicate = predicate;
+    skip_iterator.ctx = ctx;
+
+    next :: (si: ^SkipIterator($T, $Ctx)) -> (T, bool) {
+        while !si.skipped {
+            value, cont := si.iterator.next(si.iterator.data);
+
+            if !cont {
+                si.skipped = true;
+                return value, false;
+            }
+
+            if !si.predicate(value, si.ctx) {
+                si.skipped = true;
+                return value, true;
+            }
+        }
+
+        return si.iterator.next(si.iterator.data);
+    }
+
+    close :: (si: ^SkipIterator($T, $Ctx)) {
+        if si.iterator.close != null_proc do si.iterator.close(si.iterator.data);
+        raw_free(si.allocator, si);
+    }
+
+    return .{
+        data  = skip_iterator,
+        next  = #solidify next  { T=T, Ctx=Ctx },
+        close = #solidify close { T=T, Ctx=Ctx },
+    };
+}
+
 #local Zipped :: struct (T: type_expr, R: type_expr) {
     first: T;
     second: R;
index 55ed6e80161347bc7c29efa802ef62dd5744c118..bb19ac63b0b1bfe059edfa0ba69a7e5d8b8fb604 100644 (file)
@@ -138,9 +138,10 @@ contains :: (s: str, c: u8) -> bool {
 #overload
 contains :: (s: str, substr: str) -> bool {
     while i := 0; i < s.count {
+        defer i += 1;
+
         while j := 0; j < substr.count {
             if s[i + j] != substr[j] {
-                i += j + 1;
                 continue continue;
             }
 
@@ -253,17 +254,17 @@ index_of :: (s: str, c: u8) -> i32 {
 #overload
 index_of :: (s: str, substr: str) -> i32 {
     while i := 0; i < s.count {
-        start := i;
+        defer i += 1;
+
         while j := 0; j < substr.count {
             if s[i + j] != substr[j] {
-                i += j + 1;
                 continue continue;
             }
 
             j += 1;
         }
 
-        return start;
+        return i;
     }
 
     return -1;
@@ -568,6 +569,9 @@ split :: (s: str, delim: u8, allocator := context.allocator) -> []str {
     return strarr[0 .. delim_count + 1];
 }
 
+split_iter :: #match #local {}
+
+#overload
 split_iter :: (s: str, delim: u8) -> Iterator(str) {
     return iter.generator(
         ^.{ s = s, delim = delim },
@@ -584,6 +588,23 @@ split_iter :: (s: str, delim: u8) -> Iterator(str) {
     );
 }
 
+#overload
+split_iter :: (s: str, delim: str) -> Iterator(str) {
+    return iter.generator(
+        ^.{ s = s, delim = delim },
+
+        (ctx: ^$T) -> (str, bool) {
+            if string.empty(ctx.s) {
+                return "", false;
+            }
+
+            ret: str;
+            ret, ctx.s = bisect(ctx.s, ctx.delim);
+            return ret, true;
+        }
+    );
+}
+
 //
 // Splits a string into two parts, divided by the
 // first instance of the provided character. Either
@@ -610,6 +631,6 @@ bisect :: (s: str, substr: str) -> (str, str) {
         return s, "";
     }
 
-    return s[0 .. index], s[index+1 .. s.length];
+    return s[0 .. index], s[index+substr.length .. s.length];
 }