Write da_pop -- remove and return the last element:
fn da_pop(da: i64) i64 {
var len: i64 = load64(da + 8);
if (len == 0) { return 0; }
len -= 1;
store64(da + 8, len);
return load64(load64(da) + len * 8);
}
Test:
// push 10, 20, 30; pop gives 30, 20, 10
check(
\\ ... allocator and dynamic array functions ...
\\var arr: i64 = da_new();
\\da_push(arr, 10);
\\da_push(arr, 20);
\\da_push(arr, 30);
\\var a: i64 = da_pop(arr);
\\var b: i64 = da_pop(arr);
\\a * 100 + b
, 3020); // 30 * 100 + 20
### Coalescing
Our allocator has a problem: fragmentation. If you allocate and free many small blocks, the free list fills up with tiny pieces that can't satisfy larger requests -- even though the total free memory is plenty.
The fix is coalescing: when freeing a block, check if the block immediately after it in memory is also free. If so, merge them into one larger block.