diff --git a/src/content/docs/references/docs/arrays.md b/src/content/docs/references/docs/arrays.md index 59e9586..8c253fe 100644 --- a/src/content/docs/references/docs/arrays.md +++ b/src/content/docs/references/docs/arrays.md @@ -5,7 +5,8 @@ sidebar: order: 109 --- -Arrays has a central role in programming. C3 offers 2 built-in types of arrays: +Arrays has a central role in programming. C3 offers build-in arrays, slices and [vectors](/references/docs/vectors/). +The standard library enhances this further with dynamically sized arrays and other collections. ## Fixed arrays @@ -32,8 +33,6 @@ When you want to initialize a fixed array without specifying the size, use the [ int[3] a = { 1, 2, 3 }; int[*] b = { 4, 5, 6 }; // Type inferred to be int[3] - - ## Slice The final type is the slice `[]` e.g. `int[]`. A slice is a view into either a fixed or variable array. Internally it is represented as a struct containing a pointer and a size. Both fixed and variable arrays may be converted into slices, and slices may be implicitly converted to pointers: @@ -107,18 +106,19 @@ Note that all casts above are inherently unsafe and will only work if the type c For example: - int[4] a; - int[4]* b = &a; - int* c = b; - // Safe cast: - int[4]* d = (int[4]*)c; - int e = 12; - int* f = &e; - // Incorrect, but not checked - int[4]* g = (int[4]*)f; - // Also incorrect but not checked. - int[] h = f[0..2]; - +```c3 +int[4] a; +int[4]* b = &a; +int* c = b; +// Safe cast: +int[4]* d = (int[4]*)c; +int e = 12; +int* f = &e; +// Incorrect, but not checked +int[4]* g = (int[4]*)f; +// Also incorrect but not checked. +int[] h = f[0..2]; +``` #### Internals @@ -126,59 +126,97 @@ Internally the layout of a slice is guaranteed to be `struct { * ptr; usz There is a built-in struct `std::core::runtime::SubArrayContainer` which has the exact data layout of the fat array pointers. It is defined to be - struct SubArrayContainer - { - void* ptr; - usz len; - } +```c3 +struct SubArrayContainer +{ + void* ptr; + usz len; +} +``` ## Iteration over arrays -Slices, fixed and variable arrays may all be iterated over using `foreach (Type x : array)`: +You may iterate over slices, arrays and vectors using `foreach (Type x : array)`: - int[4] a = { 1, 2, 3, 5 }; - foreach (int x : a) - { - ... - } +```c3 +int[4] a = { 1, 2, 3, 5 }; +foreach (int x : a) +{ + ... +} +``` Using `&` it is possible to get an element by reference rather than by copy. Furthermore, by providing two variable name, the first is assumed to be the index: - Foo[4] a = { ... } - foreach (int idx, Foo* &f : a) - { - f.abc = idx; // Mutates the array element - } - +```c3 +Foo[4] a = { ... }; +foreach (int idx, Foo* &f : a) +{ + f.abc = idx; // Mutates the array element +} +``` It is possible to enable foreach on any type by implementing "len" and "[]" methods and annotating them using the `@operator` attribute: - struct Vector - { - usz size; - int* elements; - } +```c3 +struct DynamicArray +{ + usz count; + usz capacity; + int* elements; +} + +macro int DynamicArray.get(DynamicArray* arr, usz element) @operator([]) +{ + return arr.elements[element]; +} + +macro usz DynamicArray.count(DynamicArray* arr) @operator(len) +{ + return arr.count; +} + +fn void DynamicArray.push(DynamicArray* arr, int value) +{ + arr.ensure_capacity(arr.count + 1); // Function not shown in example. + arr.elements[arr.count++] = value; +} + +fn void test() +{ + DynamicArray v; + v.push(3); + v.push(7); - macro int Vector.get(Vector* vector, usz element) @operator([]) + // Will print 3 and 7 + foreach (int i : v) { - return vector.elements[element]; + io::printfn("%d", i); } +} +``` - macro usz Vector.size(Vector* vector) @operator(len) - { - return vector.size; - } +For more information, see [operator overloading](/references/docs/operators) - Vector v; - v.add(3); - v.add(7); +## Dynamic arrays and lists - // Will print 3 and 7 - foreach (int i : v) +The standard library offers dynamic arrays and other collections in the `std::collections` module. + +```c3 +fn void test() +{ + List() list; + list.new_init(); // Initialize the list on the heap. + list.push("Hello"); // Add the string "Hello" + list.push("World"); + foreach (s : list) { - io::printfn("%d", i); + io::printn(s); // Prints "Hello", then "World" } + String s = list[1]; // s is "World" + list.free(); // Free all memory associated with list. +} +``` -For more information, see [operator overloading](/references/docs/operators) \ No newline at end of file diff --git a/src/content/docs/references/docs/vectors.md b/src/content/docs/references/docs/vectors.md index fa4e894..f7e0845 100644 --- a/src/content/docs/references/docs/vectors.md +++ b/src/content/docs/references/docs/vectors.md @@ -11,6 +11,9 @@ types, boolean or pointers. A vector is declared similar to an array but uses `[<>]` rather than `[]`, e.g. `int[<4>]`. +(If you are searching for the counterpart of C++'s `std::vector`, look instead at the standard +library [`List` type](/references/docs/arrays/#dynamic-arrays-and-lists).) + ## Arithmetics on vectors Vectors support all arithmetics and other operations supported by its underlying type. The operations are