From: Brendan Hansen Date: Tue, 1 Sep 2020 14:33:07 +0000 (-0500) Subject: refactoring core arrays X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=c0fdb048553de4935582349d9b5c6fa448cf2fe1;p=onyx.git refactoring core arrays --- diff --git a/core/array.onyx b/core/array.onyx new file mode 100644 index 00000000..2498d4a4 --- /dev/null +++ b/core/array.onyx @@ -0,0 +1,109 @@ +package core + +// --------------------------------- +// Dynamic Arrays +// --------------------------------- +array_init :: proc (arr: ^[..] $T, initial_cap := 4) { + arr.count = 0; + arr.capacity = initial_cap; + arr.data = calloc(sizeof T * arr.capacity); +} + +array_free :: proc (arr: ^[..] $T) { + arr.count = 0; + arr.capacity = 0; + + cfree(arr.data); + arr.data = null; +} + +array_clear :: proc (arr: ^[..] $T) { + arr.count = 0; +} + +array_ensure_capacity :: proc (arr: ^[..] $T, cap: u32) { + if arr.capacity >= cap do return; + + while cap > arr.capacity do arr.capacity <<= 1; + arr.data = cresize(arr.data, sizeof T * arr.capacity); +} + +array_push :: proc (arr: ^[..] $T, x: T) { + array_ensure_capacity(arr, arr.count + 1); + arr.data[arr.count] = x; + arr.count += 1; +} + +array_insert :: proc (arr: ^[..] $T, idx: u32, x: T) { + array_ensure_capacity(arr, arr.count + 1); + + arr.count += 1; + while i := arr.count; i > idx { + arr.data[i] = arr.data[i - 1]; + i -= 1; + } + + arr.data[idx] = x; +} + +array_remove :: proc (arr: ^[..] $T, elem: T) { + move := 0; + + for i: 0, arr.count - move { + if arr.data[i + move] == elem do move += 1; + if move != 0 do arr.data[i] = arr.data[i + move]; + } + + arr.count -= move; +} + +array_delete :: proc (arr: ^[..] $T, idx: u32) { + if idx >= arr.count do return; + + for i: idx, arr.count - 1 { + arr.data[i] = arr.data[i + 1]; + } + + arr.count -= 1; +} + +array_contains :: proc (arr: ^[..] $T, x: T) -> bool { + for i: 0, arr.count do if arr.data[i] == x do return true; + return false; +} + +array_pop :: proc (arr: ^[..] $T) -> T { + arr.count -= 1; + return arr.data[arr.count]; +} + +array_average :: proc (arr: ^[..] $T) -> T { + sum := cast(T) 0; + for i: 0, arr.count { + sum += arr.data[i]; + } + + return sum / cast(T) arr.count; +} + +array_to_slice :: proc (arr: ^[..] $T) -> [] T { + return arr.data[0 : arr.count]; +} + +/* +** Simple insertion sort +** cmp should return >0 if left > right +*/ +array_sort :: proc (arr: ^[..] $T, cmp: proc (T, T) -> i32) { + for i: 1, arr.count { + x := arr.data[i]; + j := i - 1; + + while j >= 0 && cmp(arr.data[j], x) > 0 { + arr.data[j + 1] = arr.data[j]; + j -= 1; + } + + arr.data[j + 1] = x; + } +} diff --git a/core/builtin.onyx b/core/builtin.onyx index d7406441..f8b1d2dc 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -41,116 +41,7 @@ calloc :: proc (size: u32) -> rawptr do return alloc(context.allocator, size); cresize :: proc (ptr: rawptr, size: u32) -> rawptr do return resize(context.allocator, ptr, size); cfree :: proc (ptr: rawptr) do free(context.allocator, ptr); - - -// --------------------------------- -// Dynamic Arrays -// --------------------------------- -array_init :: proc (arr: ^[..] $T, initial_cap := 4) { - arr.count = 0; - arr.capacity = initial_cap; - arr.data = calloc(sizeof T * arr.capacity); -} - -array_free :: proc (arr: ^[..] $T) { - arr.count = 0; - arr.capacity = 0; - - cfree(arr.data); - arr.data = null; -} - -array_clear :: proc (arr: ^[..] $T) { - arr.count = 0; -} - -array_ensure_capacity :: proc (arr: ^[..] $T, cap: u32) { - if arr.capacity >= cap do return; - - while cap > arr.capacity do arr.capacity <<= 1; - arr.data = cresize(arr.data, sizeof T * arr.capacity); -} - -array_push :: proc (arr: ^[..] $T, x: T) { - array_ensure_capacity(arr, arr.count + 1); - arr.data[arr.count] = x; - arr.count += 1; -} - -array_insert :: proc (arr: ^[..] $T, idx: u32, x: T) { - array_ensure_capacity(arr, arr.count + 1); - - arr.count += 1; - while i := arr.count; i > idx { - arr.data[i] = arr.data[i - 1]; - i -= 1; - } - - arr.data[idx] = x; -} - -array_remove :: proc (arr: ^[..] $T, elem: T) { - move := 0; - - for i: 0, arr.count - move { - if arr.data[i + move] == elem do move += 1; - if move != 0 do arr.data[i] = arr.data[i + move]; - } - - arr.count -= move; -} - -array_delete :: proc (arr: ^[..] $T, idx: u32) { - if idx >= arr.count do return; - - for i: idx, arr.count - 1 { - arr.data[i] = arr.data[i + 1]; - } - - arr.count -= 1; -} - -array_contains :: proc (arr: ^[..] $T, x: T) -> bool { - for i: 0, arr.count do if arr.data[i] == x do return true; - return false; -} - -array_pop :: proc (arr: ^[..] $T) -> T { - arr.count -= 1; - return arr.data[arr.count]; -} - -array_average :: proc (arr: ^[..] $T) -> T { - sum := cast(T) 0; - for i: 0, arr.count { - sum += arr.data[i]; - } - - return sum / cast(T) arr.count; -} - -array_to_slice :: proc (arr: ^[..] $T) -> [] T { - return arr.data[0 : arr.count]; -} - -// -// Simple insertion sort -// cmp should return >0 if left > right -// -array_sort :: proc (arr: ^[..] $T, cmp: proc (T, T) -> i32) { - for i: 1, arr.count { - x := arr.data[i]; - j := i - 1; - - while j >= 0 && cmp(arr.data[j], x) > 0 { - arr.data[j + 1] = arr.data[j]; - j -= 1; - } - - arr.data[j + 1] = x; - } -} - +// @CLEANUP: These need to move to somewhere else eventually cmp_asc :: proc (a: $T, b: T) -> i32 do return cast(i32) (a - b); cmp_dec :: proc (a: $T, b: T) -> i32 do return cast(i32) (b - a); diff --git a/core/std/js.onyx b/core/std/js.onyx index df151685..8650a2a4 100644 --- a/core/std/js.onyx +++ b/core/std/js.onyx @@ -3,6 +3,7 @@ package core use package builtin #include_file "core/alloc" +#include_file "core/array" #include_file "core/intrinsics" #include_file "core/math" #include_file "core/memory" diff --git a/core/std/wasi.onyx b/core/std/wasi.onyx index 13c24ffb..518befb8 100644 --- a/core/std/wasi.onyx +++ b/core/std/wasi.onyx @@ -3,6 +3,7 @@ package core use package builtin #include_file "core/alloc" +#include_file "core/array" #include_file "core/file" #include_file "core/intrinsics" #include_file "core/math" diff --git a/docs/plan b/docs/plan index 32e05738..4d0d53ce 100644 --- a/docs/plan +++ b/docs/plan @@ -226,19 +226,27 @@ HOW: [X] #file and #line directives - string and u32 respectively that represent the current file and line number where the directive is - [ ] transmute - - [ ] explicit memory controls at top level - - [ ] Put type info in data section so it is runtime accessible + [ ] ** Put type info in data section so it is runtime accessible - type name - size - alignment - struct member names - array length + [ ] Type parameterized structs + + [ ] Array literals + + [ ] transmute + + [ ] explicit memory controls at top level + [ ] 'use' enums and packages at an arbitrary scope + [ ] look into creating a source map + - first-look looks really gross + - whoever came up with the source map spec should be fired... why are people so afraid of binary files?? + [ ] convert to using an 'atom' like table - All identifier tokens are given a unique atom ptr, up to string equality. - This means identifiers can be compared using ptr comparison, instead of string comparison @@ -255,8 +263,6 @@ HOW: - Compile time conditions - Only evalutate code blocks that evaluate to be true - [ ] Array literals - [ ] Top level variable initialization - Works for numeric literals @@ -267,8 +273,6 @@ HOW: [ ] All code paths return correct value - [ ] Type parameterized structs - [ ] Arrays need to be much better - Currently, they are basically just a pointer. - The length should be stored with the pointer diff --git a/onyx b/onyx index 59cbb27a..8f0b8937 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx index b8b9ba62..de6a34f6 100644 --- a/progs/poly_test.onyx +++ b/progs/poly_test.onyx @@ -42,13 +42,12 @@ Dummy :: struct { /* TODO: Make this work at some point - compose :: proc (a: $A, f: proc (A) -> $B, g: proc (B) -> $C) -> C { - return a |> f() |> g(); - } +compose :: proc (a: $A, f: proc (A) -> $B, g: proc (B) -> $C) -> C { + return a |> f() |> g(); +} */ - SOA :: struct { b : [..] i64; a : [..] i32; diff --git a/progs/stack_based.onyx b/progs/stack_based.onyx deleted file mode 100644 index 4291c9f2..00000000 --- a/progs/stack_based.onyx +++ /dev/null @@ -1,200 +0,0 @@ -package main - -#include_folder "/usr/share/onyx/core" - -#include_file "printing" -#include_file "alloc" -#include_file "string" -#include_file "wasi" - -use package printing -use package memory -use package core -use package wasi - -sort :: proc (arr: [N]i32, cmp: proc (i32, i32) -> i32) -> [N] i32 { - for i: 0, N { - smallest_idx := i; - - for j: i, N do if cmp(arr[j], arr[smallest_idx]) < 0 do smallest_idx = j; - - tmp :: arr[i]; - arr[i] = arr[smallest_idx]; - arr[smallest_idx] = tmp; - } - - return arr; -} - -ret_val :: proc (x: i32, y: i32) -> i32 { - big_arr : [128] i32; - big_arr[0] = 1234; - big_arr[1] = 1234; - big_arr[127] = 1234; - return big_arr[127] + x + y; -} - -N :: 10 - -sumN :: proc (x: [N] i32) -> i32 { - s := 0; - for i: 0, N do s += x[i]; - return s; -} - -summing :: proc (x: ^i32) -> i32 { - s := 0; - for i: 0, N do s += x[i]; - return s; -} - -get_value :: proc (x: i32, y: i32) -> i32 { - return x + 2 * y; -} - -Vec3 :: struct { - x: i32 = get_value(10, 20); - y: i32 = 0; - z: i32 = 0; -} - -SomeBigThing :: struct { - name: string; - pos: Vec3; -} - -mag_squared :: proc (use v: Vec3) -> i32 { - return x * x + y * y + z * z; -} - -clamp :: proc (v: i32, lo: i32, hi: i32) -> i32 { - if v < lo do return lo; - if v > hi do return hi; - return v; -} - -// NOTE: Anonymous functions do NOT have closure, -// so in either of these function scopes, the -// parameter 'n' is not accessible. -// -// This is intended behavior since creating new -// procs at runtime is very difficult with WASM -stupid_idea :: proc (n: i32) -> proc (i32) -> i32 { - if n == 1234 { - return proc (a: i32) -> i32 { return 5678 + a; }; - } - - return proc (a: i32) -> i32 { return -1 + a; }; -} - -some_value := 20 + 30 * 4 + 15 / 5; - -start :: proc #export { - memory_init(); - - print("Hello, World!"); - print_hex(cast(u64) some_value); - print("Hello, World!"); - print_bin(42l); - print_hex(42l); - - print(cast(u32) (#char "a" + #char "0")); - - for i: #char "a", #char "f" do print_hex(cast(u64) i); - - a := 12345; - - arr: [N][N] i32; - arr[1][0] = 10; - arr[1][1] = 20; - arr[1][2] = 30; - arr[1][3] = 40; - arr[1][4] = 50; - arr[1][9] = 123; - print(arr[1]|>sumN()); - print(summing(cast(^i32) arr[1])); - - print(10 |> ret_val(4)); - print(11 |> ret_val(5)); - - for i: 0, N do print(arr[1][i]); - - soa: struct { x: [5] i32; y: [5] i32; }; - for i: 0, 5 { - soa.x[i] = i; - soa.y[i] = i * i; - } - print(soa.y[3]); - print_ptr(^soa.y[3]); - - fancy : [5 + 3 * 4] i32; - fancy[2] = 123; - print(fancy[2]); - - - something : [N] i32; - for i: 0, N do something[i] = N - i; - for i: 0, N do print(something[i]); - - something - |> sort(proc (a: i32, b: i32) -> i32 { return a - b; }) - |> sumN() - |> clamp(30, 100) - |> print(); - - for i: 0, N do - something[i] - |> clamp(3, 6) - |> print(); - - stupid_idea(1234)(1234) |> print(); - - varr : [5] Vec3; - varr[2] = Vec3.{4, 5, 6}; - - mag_squared(varr[2]) |> print(); - - v1 := Vec3.{}; - v2 := vmul(vadd(v1, Vec3.{ 1, 2, 3 }), 3); - - print(v2.x); - print(v2.y); - print(v2.z); - - un : UnionTest; - un.f = 1.25f; - print_hex(cast(u64) un.i); - - s1 :: string_make("Hello, "); - s2 :: string_make("World!"); - s3 :: string_concat(heap_allocator, s1, s2); - defer string_free(heap_allocator, s3); - string_print(s3); - - sbt : SomeBigThing; - sbt.name = s3; - sbt.pos = Vec3.{ 2, 3, 4 }; - string_print(sbt.name); - - v := vmul(vadd(sbt.pos, Vec3.{ 1, 2, 3 }), 3); - print(v.x); - print(v.y); - print(v.z); -} - -vadd :: proc (v1: Vec3, v2: Vec3) -> Vec3 { - return Vec3.{ - v1.x + v2.x, - v1.y + v2.y, - v1.z + v2.z, - }; -} - -vmul :: proc (use v: Vec3, s: i32) -> Vec3 { - return Vec3.{ x * s, y * s, z * s }; -} - -UnionTest :: struct #union { - i : i32; - f : f32; -} diff --git a/src/onyxparser.c b/src/onyxparser.c index cd8601bb..3d7262f4 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -1238,7 +1238,7 @@ static AstType* parse_type(OnyxParser* parser, bh_arr(AstPolyParam)* poly_vars) while (parser->curr->type != ')') { if (parser->hit_unexpected_token) return root; - AstType* param_type = parse_type(parser, NULL); + AstType* param_type = parse_type(parser, poly_vars); bh_arr_push(params, param_type); if (parser->curr->type != ')') @@ -1249,7 +1249,7 @@ static AstType* parse_type(OnyxParser* parser, bh_arr(AstPolyParam)* poly_vars) AstType* return_type = (AstType *) &basic_type_void; if (parser->curr->type == Token_Type_Right_Arrow) { consume_token(parser); - return_type = parse_type(parser, NULL); + return_type = parse_type(parser, poly_vars); } u64 param_count = bh_arr_length(params);