macro (body: Code) -> i32 {
auto :: auto
- #context_scope {
- auto();
- #unquote body;
- }
+ auto();
+ #unquote body;
return 0;
}
//
// 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;
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;
}
}
}
+
+ 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 {
};
}
+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;
#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;
}
#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;
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 },
);
}
+#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
return s, "";
}
- return s[0 .. index], s[index+1 .. s.length];
+ return s[0 .. index], s[index+substr.length .. s.length];
}