Compare commits
2 commits
3045cda7a3
...
8822811dbb
| Author | SHA1 | Date | |
|---|---|---|---|
| 8822811dbb | |||
| ebe686a58b |
3 changed files with 89 additions and 44 deletions
2
TODO
2
TODO
|
|
@ -1,7 +1,6 @@
|
|||
*** IN PROGRESS ***
|
||||
|
||||
[Judah]
|
||||
065 [array] add dynamic, but stable array implementation (values should not move in memory once appended to the array; should mirror procedures on 'Static_Array')
|
||||
|
||||
[Jesse]
|
||||
011 [math] add more Vec math procedures
|
||||
|
|
@ -83,3 +82,4 @@
|
|||
024 [x] create file to document conventions/style guide
|
||||
034 [x] can we add location info to Allocator_Proc?
|
||||
012 [map] create a simple arena-backed hash map implementation 'Map(K, V)', should be able to hash a key of any type (must include: get, set, remove, for_expansion) - possibly blocked by 032
|
||||
065 [array] add dynamic, but stable array implementation (values should not move in memory once appended to the array; should mirror procedures on 'Static_Array')
|
||||
|
|
|
|||
|
|
@ -18,5 +18,3 @@
|
|||
tmath :: #import,file "./math/module.jai"(.turns, RUN_TESTS = true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
Stable_Array :: struct(T: Type, ITEMS_PER_CHUNK := 32) {
|
||||
// A dynamic array whose values will never move in memory.
|
||||
//
|
||||
// This means it is safe to take a pointer to a value within the array
|
||||
// while continuing to append to it.
|
||||
Stable_Array :: struct(T: Type, items_per_chunk := 32) {
|
||||
allocator: Allocator;
|
||||
chunks: [..]*Chunk;
|
||||
count: int;
|
||||
|
||||
Chunk :: Static_Array(ITEMS_PER_CHUNK, T);
|
||||
Chunk :: Static_Array(items_per_chunk, T);
|
||||
}
|
||||
|
||||
init :: (a: *Stable_Array, allocator: Allocator) {
|
||||
|
|
@ -13,9 +17,8 @@ init :: (a: *Stable_Array, allocator: Allocator) {
|
|||
|
||||
append :: (a: *Stable_Array) -> *a.T {
|
||||
chunk := find_or_create_chunk(a, 1);
|
||||
item := append(chunk);
|
||||
a.count += 1;
|
||||
return item;
|
||||
return append(chunk);
|
||||
}
|
||||
|
||||
append :: (a: *Stable_Array, value: a.T) -> *a.T {
|
||||
|
|
@ -26,6 +29,9 @@ append :: (a: *Stable_Array, value: a.T) -> *a.T {
|
|||
}
|
||||
|
||||
append :: (a: *Stable_Array, values: ..a.T) -> *a.T {
|
||||
// @todo(judah): this should look for chunks where can just copy values directly
|
||||
// rather than calling append for each one.
|
||||
|
||||
first: *a.T;
|
||||
for values {
|
||||
if first == null {
|
||||
|
|
@ -46,39 +52,44 @@ reset :: (a: *Stable_Array) {
|
|||
}
|
||||
|
||||
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];
|
||||
cidx := index / a.items_per_chunk;
|
||||
iidx := index % a.items_per_chunk;
|
||||
meta.check_bounds(cidx, a.chunks.count, loc = loc);
|
||||
meta.check_bounds(iidx, a.chunks[cidx].count, loc = loc);
|
||||
return a.chunks[cidx].items[iidx];
|
||||
}
|
||||
|
||||
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];
|
||||
cidx := index / a.items_per_chunk;
|
||||
iidx := index % a.items_per_chunk;
|
||||
meta.check_bounds(cidx, a.chunks.count, loc = loc);
|
||||
meta.check_bounds(iidx, a.chunks[cidx].count, loc = loc);
|
||||
return *a.chunks[cidx].items[iidx];
|
||||
}
|
||||
|
||||
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;
|
||||
cidx := index / a.items_per_chunk;
|
||||
iidx := index % a.items_per_chunk;
|
||||
meta.check_bounds(cidx, a.chunks.count, loc = loc);
|
||||
meta.check_bounds(iidx, a.chunks[cidx].count, loc = loc);
|
||||
a.chunks[cidx].items[iidx] = value;
|
||||
}
|
||||
|
||||
for_expansion :: (a: Stable_Array, body: Code, flags: For_Flags) #expand {
|
||||
for i: 0..a.count - 1 {
|
||||
`it := a[i];
|
||||
for #v2 <=(flags & .REVERSE == .REVERSE) i: 0..a.count - 1 {
|
||||
`it_index := i;
|
||||
#if flags & .POINTER == .POINTER {
|
||||
`it := *a[i];
|
||||
}
|
||||
else {
|
||||
`it := a[i];
|
||||
}
|
||||
|
||||
#insert,scope(body) body;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#scope_file;
|
||||
|
||||
mem :: #import "jc/memory";
|
||||
|
|
@ -90,7 +101,7 @@ find_or_create_chunk :: (a: *Stable_Array, amount: int) -> *a.Chunk {
|
|||
}
|
||||
|
||||
last := a.chunks[a.chunks.count - 1];
|
||||
if amount > a.ITEMS_PER_CHUNK - last.count {
|
||||
if amount > a.items_per_chunk - last.count {
|
||||
last = create_chunk(a);
|
||||
}
|
||||
|
||||
|
|
@ -111,24 +122,60 @@ try_lazy_init :: (a: *Stable_Array) {
|
|||
}
|
||||
}
|
||||
|
||||
// #run {
|
||||
// #import "Basic";
|
||||
|
||||
// {
|
||||
// a: Stable_Array(int);
|
||||
// for 0..64 {
|
||||
// append(*a, it * it);
|
||||
// }
|
||||
// ----------------------------------------------------------
|
||||
// TESTS
|
||||
// ----------------------------------------------------------
|
||||
|
||||
// reset(*a);
|
||||
basic :: #import "Basic";
|
||||
|
||||
// append(*a, 10);
|
||||
// append(*a, 20);
|
||||
// append(*a, 30);
|
||||
#if RUN_TESTS #run {
|
||||
test :: #import "jc/test";
|
||||
|
||||
// for a {
|
||||
// print("%: %\n", it_index, it);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
test.run("basic operations", t => {
|
||||
a: Stable_Array(int, 4);
|
||||
|
||||
append(*a, 10, 20, 30, 40);
|
||||
test.expect(t, a.count == 4);
|
||||
test.expect(t, a.chunks.count == 1, "chunk count was %", a.chunks.count);
|
||||
|
||||
append(*a, 50);
|
||||
test.expect(t, a.count == 5);
|
||||
test.expect(t, a.chunks.count == 2, "chunk count was %", a.chunks.count);
|
||||
|
||||
append(*a, 60, 70, 80, 90, 100, 110, 120);
|
||||
test.expect(t, a.count == 12);
|
||||
test.expect(t, a.chunks.count == 3, "chunk count was %", a.chunks.count);
|
||||
|
||||
for a {
|
||||
test.expect(t, it == (it_index + 1) * 10, "% was %", it, (it_index + 1) * 10);
|
||||
}
|
||||
});
|
||||
|
||||
test.run("iteration", t => {
|
||||
a: Stable_Array(int);
|
||||
append(*a, 10, 20, 30, 40);
|
||||
|
||||
last := 999;
|
||||
for < a {
|
||||
test.expect(t, it == (it_index + 1) * 10);
|
||||
test.expect(t, it < last);
|
||||
|
||||
last = it;
|
||||
}
|
||||
|
||||
for * a it.* = 1;
|
||||
for a test.expect(t, it == 1);
|
||||
});
|
||||
|
||||
test.run("stability", t => {
|
||||
a: Stable_Array(int, 1);
|
||||
|
||||
first := append(*a, 10);
|
||||
addr := first.(u64);
|
||||
for 0..10 append(*a, it * 10);
|
||||
|
||||
test.expect(t, first.(u64) == addr);
|
||||
test.expect(t, first.* == 10);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue