Stable_Array :: struct(T: Type, ITEMS_PER_CHUNK := 32) { allocator: Allocator; chunks: [..]*Chunk; count: int; Chunk :: Static_Array(ITEMS_PER_CHUNK, T); } init :: (a: *Stable_Array, allocator: Allocator) { a.allocator = allocator; a.chunks.allocator = allocator; } append :: (a: *Stable_Array) -> *a.T { chunk := find_or_create_chunk(a, 1); item := append(chunk); a.count += 1; return item; } append :: (a: *Stable_Array, value: a.T) -> *a.T { chunk := find_or_create_chunk(a, 1); item := append(chunk, value); a.count += 1; return item; } append :: (a: *Stable_Array, values: ..a.T) -> *a.T { first: *a.T; for values { if first == null { first = inline append(a, it); } else { inline append(a, it); } } return first; } reset :: (a: *Stable_Array) { for a.chunks it.count = 0; a.count = 0; a.chunks.count = 0; } operator [] :: (a: Stable_Array, index: int, loc := #caller_location) -> a.T #no_abc { b_idx := index / a.ITEMS_PER_CHUNK; i_idx := index % a.ITEMS_PER_CHUNK; meta.check_bounds(b_idx, a.chunks.count, loc = loc); meta.check_bounds(i_idx, a.chunks[b_idx].count, loc = loc); return a.chunks[b_idx].items[i_idx]; } operator *[] :: (a: *Stable_Array, index: int, loc := #caller_location) -> *a.T #no_abc { b_idx := index / a.ITEMS_PER_CHUNK; i_idx := index % a.ITEMS_PER_CHUNK; meta.check_bounds(b_idx, a.chunks.count, loc = loc); meta.check_bounds(i_idx, a.chunks[b_idx].count, loc = loc); return *a.chunks[b_idx].items[i_idx]; } operator []= :: (a: *Stable_Array, index: int, value: a.T, loc := #caller_location) #no_abc { c_idx := index / a.ITEMS_PER_CHUNK; i_idx := index % a.ITEMS_PER_CHUNK; meta.check_bounds(c_idx, a.chunks.count, loc = loc); meta.check_bounds(i_idx, a.chunks[b_idx].count, loc = loc); chunk := a.chunks[c_idx]; chunk.items[i_idx] = value; } for_expansion :: (a: Stable_Array, body: Code, flags: For_Flags) #expand { for i: 0..a.count - 1 { `it := a[i]; `it_index := i; #insert,scope(body) body; } } #scope_file; mem :: #import "jc/memory"; meta :: #import "jc/meta"; find_or_create_chunk :: (a: *Stable_Array, amount: int) -> *a.Chunk { if a.chunks.count == 0 { return create_chunk(a); } last := a.chunks[a.chunks.count - 1]; if amount > a.ITEMS_PER_CHUNK - last.count { last = create_chunk(a); } return last; } create_chunk :: (a: *Stable_Array) -> *a.Chunk { inline try_lazy_init(a); chunk := mem.request_memory(a.Chunk,, allocator = a.allocator); append(*a.chunks, chunk); return chunk; } try_lazy_init :: (a: *Stable_Array) { if a.allocator.proc == null { init(a, context.allocator); } } // #run { // #import "Basic"; // { // a: Stable_Array(int); // for 0..64 { // append(*a, it * it); // } // reset(*a); // append(*a, 10); // append(*a, 20); // append(*a, 30); // for a { // print("%: %\n", it_index, it); // } // } // }