made the array functions work with slices too
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 10 Sep 2021 20:55:27 +0000 (15:55 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 10 Sep 2021 20:55:27 +0000 (15:55 -0500)
bin/onyx
core/container/array.onyx
core/container/set.onyx
modules/immediate_mode/immediate_renderer.onyx
modules/wasm_utils/parser.onyx
src/polymorph.c
tests/aoc-2020/day10.onyx
tests/aoc-2020/day19.onyx
tests/aoc-2020/day21.onyx
tests/aoc-2020/day23.onyx
tests/aoc-2020/day5.onyx

index 0857ba0003720aa0040b276d1fba7f8f70e7e13f..fec3be71882c3b62898f97275da7d04413f84c89 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 2998fcb42325429ab97e1ee740e0bdee00384051..ceca3ae41f52788723f40e162886b7b25b1f7884 100644 (file)
@@ -5,7 +5,7 @@ use package core.intrinsics.onyx { __zero_value }
 // [..] T == Array(T)
 //   where
 // Array :: struct (T: type_expr) {
-//     data      : T;
+//     data      : ^T;
 //     count     : u32;
 //     capacity  : u32;
 //     allocator : Allocator;
@@ -139,7 +139,61 @@ pop :: (arr: ^[..] $T) -> T {
     return arr.data[arr.count];
 }
 
-transplant :: (arr: ^[..] $T, old_index: i32, new_index: i32) -> bool {
+concat :: (arr: ^[..] $T, other: [..] T) {
+    for ^o: other do push(arr, *o);
+}
+
+
+fold_idx_elem :: #match {
+    (arr: ^[..] $T, cmp: (T, T) -> bool) -> (i32, T) {
+        return fold_idx_elem(arr.data, arr.count, cmp);
+    },
+
+    (arr: ^$T, count: i32, cmp: (T, T) -> bool) -> (i32, T) {
+        idx  := 0;
+        elem := arr[0];
+        
+        for i: 1 .. count {
+            if cmp(arr[i], elem) {
+                idx  = i;
+                elem = arr[i];
+            }
+        }
+        
+        return idx, elem;
+    },
+}
+
+#private_file cmp_greater :: (x: $T, y: T) -> bool do return x > y;
+#private_file cmp_less    :: (x: $T, y: T) -> bool do return x < y;
+
+greatest :: #match {
+    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
+    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
+    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_greater); },
+}
+
+least :: #match {
+    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
+    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
+    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_less); },
+}
+
+
+// Useful structure when talking about dynamic arrays where you don't know of what
+// type they store. For example, when passing a dynamic array as an 'any' argument.
+Untyped_Array :: struct {
+    data: rawptr;
+    count: u32;
+    capacity: u32;
+    allocator: Allocator;
+}
+
+
+
+// Things that work with slices and arrays
+
+transplant :: (arr: [] $T, old_index: i32, new_index: i32) -> bool {
     if old_index < 0 || old_index >= arr.count do return false;
     if new_index < 0 || new_index >= arr.count do return false;
     if old_index == new_index do return true;
@@ -163,7 +217,7 @@ transplant :: (arr: ^[..] $T, old_index: i32, new_index: i32) -> bool {
     return true;
 }
 
-get :: (arr: ^[..] $T, idx: i32) -> T {
+get :: (arr: [] $T, idx: i32) -> T {
     if arr.count == 0 do return __zero_value(T);
 
     while idx < 0          do idx += arr.count;
@@ -172,7 +226,7 @@ get :: (arr: ^[..] $T, idx: i32) -> T {
     return arr.data[idx];
 }
 
-get_ptr :: (arr: ^[..] $T, idx: i32) -> ^T {
+get_ptr :: (arr: [] $T, idx: i32) -> ^T {
     if arr.count == 0 do return null;
 
     while idx < 0          do idx += arr.count;
@@ -181,7 +235,7 @@ get_ptr :: (arr: ^[..] $T, idx: i32) -> ^T {
     return ^arr.data[idx];
 }
 
-set :: (arr: ^[..] $T, idx: i32, value: T) {
+set :: (arr: [] $T, idx: i32, value: T) {
     if arr.count == 0 do return;
 
     while idx < 0          do idx += arr.count;
@@ -190,75 +244,38 @@ set :: (arr: ^[..] $T, idx: i32, value: T) {
     arr.data[idx] = value;
 }
 
-concat :: (arr: ^[..] $T, other: [..] T) {
-    for ^o: other do push(arr, *o);
-}
-
 // Uses '==' to compare for equality.
-contains :: #match {
-    (arr: ^[..] $T, x: T) -> bool {
-        for it: *arr do if it == x do return true;
-        return false;
-    },
-
-    (arr: [] $T, x: T) -> bool {
-        for it: arr do if it == x do return true;
-        return false;
-    }
+contains :: (arr: [] $T, x: T) -> bool {
+    for it: arr do if it == x do return true;
+    return false;
 }
 
 // Uses '+' to sum.
-sum :: #match {
-    (arr: ^[..] $T, start: T = 0) -> T {
-        sum := start;
-        for it: *arr do sum += it;
-        return sum;
-    },
-
-    (arr: [] $T, start: T = 0) -> T {
-        sum := start;
-        for it: arr do sum += it;
-        return sum;
-    }
+sum :: (arr: [] $T, start: T = 0) -> T {
+    sum := start;
+    for it: arr do sum += it;
+    return sum;
 }
 
-product :: #match {
-    (arr: ^[..] $T, start: T = 1) -> T {
-        sum := start;
-        for it: *arr do sum *= it;
-        return sum;
-    },
-
-    (arr: [] $T, start: T = 1) -> T {
-        sum := start;
-        for it: arr do sum *= it;
-        return sum;
-    }
+product :: (arr: [] $T, start: T = 1) -> T {
+    prod := start;
+    for it: arr do prod *= it;
+    return prod;
 }
 
-average :: (arr: ^[..] $T) -> T {
+average :: (arr: [] $T) -> T {
     sum := cast(T) 0;
     for it: *arr do sum += it;
 
     return sum / cast(T) arr.count;
 }
 
-to_slice :: #match {
-    (arr: [..] $T) -> [] T {
-        return arr.data[0 .. arr.count];
-    },
-
-    (arr: ^[..] $T) -> [] T {
-        return arr.data[0 .. arr.count];
-    },
-}
-
-/*
-** Simple insertion sort
-**    cmp should return >0 if left > right
-*/
+//
+// Simple insertion sort
+//    cmp should return >0 if left > right
+//
 sort :: #match {
-    (arr: ^[..] $T, cmp: (T, T) -> i32) {
+    (arr: [] $T, cmp: (T, T) -> i32) {
         for i: 1 .. arr.count {
             x := arr.data[i];
             j := i - 1;
@@ -277,7 +294,7 @@ sort :: #match {
         }
     },
 
-    (arr: ^[..] $T, cmp: (^T, ^T) -> i32) {
+    (arr: [] $T, cmp: (^T, ^T) -> i32) {
         for i: 1 .. arr.count {
             j := i;
 
@@ -293,26 +310,13 @@ sort :: #match {
     }
 }
 
-fold :: #match {
-    (arr: ^[..] $T, init: $R, f: (T, R) -> R) -> R {
-        val := init;
-        for it: *arr do val = f(it, val);
-        return val;
-    },
-
-    (arr: [] $T, init: $R, f: (T, R) -> R) -> R {
-        val := init;
-        for it: arr do val = f(it, val);
-        return val;
-    }
+fold :: (arr: [] $T, init: $R, f: (T, R) -> R) -> R {
+    val := init;
+    for it: arr do val = f(it, val);
+    return val;
 }
 
 map :: #match {
-    macro (arr: [..] $T, f: (^T) -> void)              do for ^it: arr do f(it);,
-    macro (arr: [..] $T, f: (T) -> T)                  do for ^it: arr do *it = f(*it);,
-    macro (arr: [..] $T, body: Code)                   do for ^it: arr do #insert body;,
-    macro (arr: [..] $T, data: $R, f: (^T, R) -> void) do for ^it: arr do f(it, data);,
-    macro (arr: [..] $T, data: $R, f: (T, R) -> T)     do for ^it: arr do *it = f(*it, data);,
     macro (arr: [] $T, f: (^T) -> void)                do for ^it: arr do f(it);,
     macro (arr: [] $T, f: (T) -> T)                    do for ^it: arr do *it = f(*it);,
     macro (arr: [] $T, body: Code)                     do for ^it: arr do #insert body;,
@@ -320,45 +324,45 @@ map :: #match {
     macro (arr: [] $T, data: $R, f: (T, R) -> T)       do for ^it: arr do *it = f(*it, data);,
 }
 
-every :: (arr: ^[..] $T, predicate: (T) -> bool) -> bool {
+every :: (arr: [] $T, predicate: (T) -> bool) -> bool {
     val := true;
-    for ^it: *arr do val = val && predicate(*it);
+    for ^it: arr do val = val && predicate(*it);
     return val;
 }
 
-some :: (arr: ^[..] $T, predicate: (T) -> bool) -> bool {
+some :: (arr: [] $T, predicate: (T) -> bool) -> bool {
     val := false;
-    for ^it: *arr {
+    for ^it: arr {
         val = val || predicate(*it);
         if val do break;
     }
     return val;
 }
 
-fill :: (arr: ^[..] $T, value: T) {
+fill :: (arr: [] $T, value: T) {
     for i: arr.count {
-        arr.data[i] = value;
+        arr[i] = value;
     }
 }
 
-fill_range :: (arr: ^[..] $T, r: range, value: T) {
+fill_range :: (arr: [] $T, r: range, value: T) {
     for i: r {
         if i >= arr.count || i < 0 do continue;
-        arr.data[i] = value;
+        arr[i] = value;
     }
 }
 
-to_list :: (arr: ^[..] $T, allocator := context.allocator) -> List(T) {
+to_list :: (arr: [] $T, allocator := context.allocator) -> List(T) {
     new_list := list.make(T, allocator);
 
-    for ^it: *arr {
+    for ^it: arr {
         list.push_end(^new_list, *it);
     }
 
     return new_list;
 }
 
-find :: (arr: ^[..] $T, value: T) -> i32 {
+find :: (arr: [] $T, value: T) -> i32 {
     for i: arr.count {
         if value == arr.data[i] do return i;
     }
@@ -366,33 +370,23 @@ find :: (arr: ^[..] $T, value: T) -> i32 {
     return -1;
 }
 
-find_ptr :: (arr: ^[..] $T, value: T) -> ^T {
-    for ^it: *arr {
+find_ptr :: (arr: [] $T, value: T) -> ^T {
+    for ^it: arr {
         if value == *it do return it;
     }
 
     return null;
 }
 
-first :: #match {
-    (arr: ^[..] $T, predicate: (T) -> bool) -> ^T {
-        first((#type [] T).{ arr.data, arr.count }, predicate);
-    },
-
-    (arr: [] $T, predicate: (T) -> bool) -> ^T {
-        for ^it: arr {
-            if predicate(*it) do return it;
-        }
+first :: (arr: [] $T, predicate: (T) -> bool) -> ^T {
+    for ^it: arr {
+        if predicate(*it) do return it;
+    }
 
-        return null;
-    },
+    return null;
 }
 
 count_where :: #match {
-    (arr: ^[..] $T, predicate: $Pred) -> u32 {
-        return count_where((#type [] T).{ arr.data, arr.count }, predicate);
-    },
-
     (arr: [] $T, predicate: (T) -> bool) -> u32 {
         count: u32 = 0;
         for ^it: arr do if predicate(*it) do count += 1;
@@ -406,47 +400,3 @@ count_where :: #match {
     },
 }
 
-fold_idx_elem :: #match {
-    (arr: ^[..] $T, cmp: (T, T) -> bool) -> (i32, T) {
-        return fold_idx_elem(arr.data, arr.count, cmp);
-    },
-
-    (arr: ^$T, count: i32, cmp: (T, T) -> bool) -> (i32, T) {
-        idx  := 0;
-        elem := arr[0];
-        
-        for i: 1 .. count {
-            if cmp(arr[i], elem) {
-                idx  = i;
-                elem = arr[i];
-            }
-        }
-        
-        return idx, elem;
-    },
-}
-
-#private_file cmp_greater :: (x: $T, y: T) -> bool do return x > y;
-#private_file cmp_less    :: (x: $T, y: T) -> bool do return x < y;
-
-greatest :: #match {
-    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
-    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_greater); },
-    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_greater); },
-}
-
-least :: #match {
-    (arr: [..] $T) -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
-    (arr: [] $T)   -> (i32, T) { return fold_idx_elem(arr.data, arr.count, cmp_less); },
-    (arr: [$N] $T) -> (i32, T) { return fold_idx_elem(cast(^T) arr, N,     cmp_less); },
-}
-
-
-// Useful structure when talking about dynamic arrays where you don't know of what
-// type they store. For example, when passing a dynamic array as an 'any' argument.
-Untyped_Array :: struct {
-    data: rawptr;
-    count: u32;
-    capacity: u32;
-    allocator: Allocator;
-}
index e15a43a7ec47037fae5826c706a8d7ab4636507b..1946ee600f8a1abb9b05466a1ba4b08689e9b1b6 100644 (file)
@@ -25,7 +25,7 @@ make :: ($T: type_expr, default := __zero_value(T), hash_count: i32 = 16) -> Set
 init :: (use set: ^Set($T), default := __zero_value(T), hash_count: i32 = 16) {
     array.init(^hashes, hash_count);
     hashes.count = hash_count;
-    array.fill(^hashes, -1);
+    array.fill(hashes, -1);
 
     array.init(^entries, 4); 
 
index f34242d9660ad640c4d7ee657d964d41440f436a..ccdf9acb887187dbc818d76f92b82d283444883a 100644 (file)
@@ -92,7 +92,7 @@ Immediate_Renderer :: struct {
 
         world_transform_stack = array.make(Transform, capacity=1);
         array.insert_empty(^world_transform_stack, 0);
-        transform_identity(array.get_ptr(^world_transform_stack, -1));
+        transform_identity(array.get_ptr(world_transform_stack, -1));
 
         scissor_stack = array.make(Scissor_State);
     
@@ -128,7 +128,7 @@ Immediate_Renderer :: struct {
 
         gl.bindBuffer(gl.ARRAY_BUFFER, -1);
 
-        world_transform := array.get_ptr(^world_transform_stack, -1);
+        world_transform := array.get_ptr(world_transform_stack, -1);
         world_matrix := transform_to_matrix(world_transform);
 
         gl.uniformMatrix4(shader.world_uniform, false, world_matrix);
@@ -148,7 +148,7 @@ Immediate_Renderer :: struct {
 
         if world_transform_dirty {
             world_transform_dirty = false;
-            world_transform := array.get_ptr(^world_transform_stack, -1);
+            world_transform := array.get_ptr(world_transform_stack, -1);
             world_matrix := transform_to_matrix(world_transform);
 
             for shader: (#type ^Shader).[ ^simple_shader, ^textured_shader, ^alpha_shader ] {
@@ -384,7 +384,7 @@ Immediate_Renderer :: struct {
         world_transform_dirty = true;
 
         array.push(^world_transform_stack, world_transform_stack[world_transform_stack.count - 1]);
-        *array.get_ptr(^world_transform_stack, -1) = *array.get_ptr(^world_transform_stack, -2);
+        *array.get_ptr(world_transform_stack, -1) = *array.get_ptr(world_transform_stack, -2);
 
         // transform_identity(array.get_ptr(^world_transform_stack, -1));
     }
@@ -397,15 +397,15 @@ Immediate_Renderer :: struct {
     }
 
     identity :: (use ir: ^Immediate_Renderer) {
-        transform_identity(array.get_ptr(^world_transform_stack, -1));
+        transform_identity(array.get_ptr(world_transform_stack, -1));
     }
 
     get_transform :: (use ir: ^Immediate_Renderer) -> ^Transform {
-        return array.get_ptr(^world_transform_stack, -1);
+        return array.get_ptr(world_transform_stack, -1);
     }
 
     apply_transform :: (use ir: ^Immediate_Renderer, transform: Transform) {
-        transform_apply(array.get_ptr(^world_transform_stack, -1), transform);
+        transform_apply(array.get_ptr(world_transform_stack, -1), transform);
         world_transform_dirty = true;
     }
 
@@ -526,4 +526,4 @@ save_matrix :: macro () {
 
     I.push_matrix();
     defer I.pop_matrix();
-}
\ No newline at end of file
+}
index 3475f97cb0ab4ea3a40350d1e2142ec36703b04e..7d83b963a79b5ab1b2b5750d6721cfdf171d06d3 100644 (file)
@@ -275,8 +275,7 @@ parse_code_section :: (use bin: ^WasmBinary, allocator := context.allocator) ->
         _, pos := io.stream_tell(reader.stream);
         io.stream_seek(reader.stream, before_locals + size, .Start);
 
-        locals_slice := array.copy_range(^locals, 0 .. local_index, allocator=wasm_allocator)
-                        |> array.to_slice();
+        locals_slice: [] WasmLocal = array.copy_range(^locals, 0 .. local_index, allocator=wasm_allocator);
 
         return .{ size, locals_slice, pos };
     }
index e5e709711052ad8358dfae08b637ac550f47ae38..7fa6442b7eae2489a62d2ef352284121b8e349c1 100644 (file)
@@ -277,11 +277,13 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type
             }
 
             case Ast_Kind_Slice_Type: {
-                if (elem.actual->kind != Type_Kind_Slice) break;
+                if (elem.actual->kind != Type_Kind_Slice && elem.actual->kind != Type_Kind_DynArray && elem.actual->kind != Type_Kind_VarArgs) break;
 
                 bh_arr_push(elem_queue, ((PolySolveElem) {
                     .type_expr = ((AstSliceType *) elem.type_expr)->elem,
                     .kind = PSK_Type,
+
+                    // HACK: This makes the assumption that slices, dynamic arrays and varargs have the same element type at the same location.
                     .actual = elem.actual->Slice.elem,
                 }));
                 break;
index 81fa274685ad12a07e88b4415c25f8910eb0a86a..31f764e8b0881e0d6c20d970996b816955918d92 100644 (file)
@@ -40,7 +40,7 @@ main :: (args: [] cstr) {
     array.push(^nums, 0);
 
     cmp_asc :: (a: $T, b: T) -> i32 do return ~~(a - b);
-    array.sort(^nums, cmp_asc);
+    array.sort(nums, cmp_asc);
 
     diffs: [3] u32;
     for ^d: diffs do *d = 0;
index 3327b85f436d74f47cdfc5ddb8967fe0bd51553a..1adaed1ffe09d4a9a1f0edb7d986b96f04e23f99 100644 (file)
@@ -63,11 +63,11 @@ grammar_prepare :: (use g: ^Grammar) {
         }
     }
 
-    array.sort(^terminate_rules, (a: Term, b: Term) -> i32 {
+    array.sort(terminate_rules, (a: Term, b: Term) -> i32 {
         return (cast(i32) a.nt) - (cast(i32) b.nt);
     });
 
-    array.sort(^production_rules, (a: Prod, b: Prod) -> i32 {
+    array.sort(production_rules, (a: Prod, b: Prod) -> i32 {
         return (cast(i32) a.nt0) - (cast(i32) b.nt0);
     });
 
index f10729d8df658962b2b2ce655365e8f273eeb32f..a2326d1a9cf8fd44876eca082c3d7553a5bd6a3b 100644 (file)
@@ -143,7 +143,7 @@ main :: (args: [] cstr) {
                 matches := true;
 
                 for ap: allergen_entry.value.appears_on {
-                    if !array.contains(^ingredient_entry.value.appears_on, ap) do matches = false;
+                    if !array.contains(ingredient_entry.value.appears_on, ap) do matches = false;
                 }
 
                 if matches {
@@ -162,7 +162,7 @@ main :: (args: [] cstr) {
         }
     }
 
-    array.sort(^matched_ingredients, (i1: ^Ingredient, i2: ^Ingredient) -> i32 {
+    array.sort(matched_ingredients, (i1: ^Ingredient, i2: ^Ingredient) -> i32 {
         return string.compare(i1.allergen, i2.allergen);
     });
 
index 7f64f0cc2a1f7cd96755013232a2bf0af3651701..b51cf013b71c5cc2de14c0aeaaab79fcb40a6aaa 100644 (file)
@@ -68,7 +68,7 @@ main :: (args: [] cstr) {
     
     // Part 2
     for i: 9 .. 1000000 do array.push(^cups, i);
-    simulate(array.to_slice(^cups), 10000000);
+    simulate(cups, 10000000);
 
     // Undo the zero-indexing
     for ^cup: cups do *cup += 1;
@@ -81,7 +81,7 @@ main :: (args: [] cstr) {
     // printf("\n");
 
     // Part 2
-    one_idx := get_idx(array.to_slice(^cups), 1);
+    one_idx := get_idx(cups, 1);
     prod: i64 = cast(i64) (cups[w(one_idx + 1)]) * cast(i64) (cups[w(one_idx + 2)]);
     printf("Cup product: {}\n", prod);
 }
index 0fa916201c900e3f9b9323ad013eda08879ee45e..98bc6f369333066ce83d59b8344f25fa62bd7747 100644 (file)
@@ -26,7 +26,7 @@ main :: (args: [] cstr) {
     }
 
     missing := 0;
-    array.sort(^vals, cmp_asc);
+    array.sort(vals, cmp_asc);
     for i: 0 .. vals.count - 1 {
         if vals[i + 1] - vals[i] != 1 do missing = vals[i] + 1;
     }