fixes
This commit is contained in:
parent
872689bb42
commit
dc8b8e4f26
7 changed files with 207 additions and 208 deletions
|
|
@ -1,8 +1,5 @@
|
|||
// @todo(judah): Conditionally added to the context because it causes some weirdness in tests
|
||||
#if !RunTests {
|
||||
#add_context arena := Arena.{ proc = PagingArenaProc };
|
||||
#add_context temp_arena := Arena.{ proc = TempArenaProc };
|
||||
}
|
||||
#add_context arena := Arena.{ proc = PagingArenaProc };
|
||||
#add_context temp_arena := Arena.{ proc = TempArenaProc };
|
||||
|
||||
Arena :: struct {
|
||||
proc: ArenaProc;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
/// Note: If no allocator has been set, ArrayAppend will use the current context allocator.
|
||||
/// Note: Calls to Append may invalidate pre-existing pointers.
|
||||
ArrayAppend :: inline (arr: *[..]$T, values: ..T) -> *T {
|
||||
TrySetAllocator(arr);
|
||||
TrySetAllocator(arr,, allocator = ArenaToAllocator(*context.arena));
|
||||
|
||||
if values.count == 0 {
|
||||
return basic.array_add(arr);
|
||||
|
|
@ -23,7 +23,7 @@ ArrayGrow :: inline (arr: *[..]$T, new_count: int) {
|
|||
if new_count <= arr.allocated
|
||||
{ return; }
|
||||
|
||||
TrySetAllocator(arr);
|
||||
TrySetAllocator(arr,, allocator = ArenaToAllocator(*context.arena));
|
||||
basic.array_reserve(arr, new_count,, allocator = arr.allocator);
|
||||
}
|
||||
|
||||
|
|
@ -58,18 +58,6 @@ ArrayEquals :: (lhs: []$T, rhs: []T) -> bool {
|
|||
return MemEqual(lhs.data, rhs.data, lhs.count * size_of(T));
|
||||
}
|
||||
|
||||
CheckBounds :: ($$index: $T, $$count: T, loc := #caller_location) #expand {
|
||||
Message :: "bounds check failed!";
|
||||
#if is_constant(index) && is_constant(count) {
|
||||
if index < 0 || index >= count {
|
||||
CompileError(Message, loc = loc);
|
||||
}
|
||||
}
|
||||
else if index < 0 || index > count {
|
||||
Panic(Message, loc = loc);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayIndex :: struct(T: Type) {
|
||||
value: T = ---;
|
||||
index: int;
|
||||
|
|
@ -157,89 +145,19 @@ ArrayTrim :: (view: []$T, cutset: []T, $flags: ArrayTrimFlags = .FromStart) -> [
|
|||
}
|
||||
|
||||
|
||||
CheckBounds :: ($$index: $T, $$count: T, loc := #caller_location) #expand {
|
||||
Message :: "bounds check failed!";
|
||||
#if is_constant(index) && is_constant(count) {
|
||||
if index < 0 || index >= count {
|
||||
CompileError(Message, loc = loc);
|
||||
}
|
||||
}
|
||||
else if index < 0 || index > count {
|
||||
Panic(Message, loc = loc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#scope_file
|
||||
|
||||
basic :: #import "Basic"; // @future
|
||||
|
||||
#if RunTests #run,stallable {
|
||||
Test("slice", t => {
|
||||
a1 := int.[ 1, 2, 3, 4, 5 ];
|
||||
a2 := ArraySlice(a1, 2);
|
||||
Expect(a2.count == 3);
|
||||
Expect(ArrayEquals(a2, int.[ 3, 4, 5 ]));
|
||||
|
||||
b1 := int.[ 1, 2, 3, 4, 5 ];
|
||||
b2 := ArraySlice(b1, 2, 0);
|
||||
Expect(b2.count == 0);
|
||||
Expect(b2.data == b1.data + 2);
|
||||
|
||||
c1 := int.[ 1, 2, 3, 4, 5 ];
|
||||
c2 := ArraySlice(c1, 3, 1);
|
||||
Expect(c2.count == 1);
|
||||
Expect(ArrayEquals(c2, int.[ 4 ]));
|
||||
|
||||
d1 := int.[ 1, 2, 3 ];
|
||||
d2 := ArraySlice(d1, 2);
|
||||
Expect(d2.count == 1);
|
||||
Expect(ArrayEquals(d2, int.[ 3 ]));
|
||||
});
|
||||
|
||||
Test("find", t => {
|
||||
a := int.[ 1, 2, 3, 4, 5 ];
|
||||
|
||||
ok, res := ArrayFind(a, 3);
|
||||
Expect(ok && res.index == 2);
|
||||
Expect(res.value == 3);
|
||||
|
||||
ok, res = ArrayFind(a, -1);
|
||||
Expect(!ok && res.index == -1);
|
||||
|
||||
b := int.[ 1, 2, 2, 3, 4, 5, 2 ];
|
||||
|
||||
ok, res = ArrayFind(b, 2);
|
||||
Expect(ok && res.index == 1);
|
||||
|
||||
ok, res = ArrayFind(b, 2, .FromEnd);
|
||||
Expect(ok && res.index == 6);
|
||||
|
||||
c := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
|
||||
ok, res = ArrayFind(c, 0, .Last);
|
||||
Expect(ok && res.index == 8);
|
||||
|
||||
ok, res = ArrayFind(c, 0, .FromEnd | .Last);
|
||||
Expect(ok && res.index == 0);
|
||||
});
|
||||
|
||||
Test("contains", t => {
|
||||
a := int.[ 1, 2, 3, 4, 5 ];
|
||||
Expect(ArrayContains(a, 3));
|
||||
Expect(!ArrayContains(a, -1));
|
||||
});
|
||||
|
||||
Test("trim", t => {
|
||||
a1 := int.[ 0, 0, 0, 1, 2, 3 ];
|
||||
a2 := ArrayTrim(a1, .[ 0 ]);
|
||||
Expect(ArrayEquals(a1, .[ 0, 0, 0, 1, 2, 3 ]));
|
||||
Expect(ArrayEquals(a2, .[ 1, 2, 3 ]));
|
||||
|
||||
b1 := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
b2 := ArrayTrim(b1, .[ 0 ], .FromEnd);
|
||||
Expect(ArrayEquals(b1, .[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(b2, .[ 0, 0, 0, 1, 2, 3 ]));
|
||||
|
||||
c1 := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
c2 := ArrayTrim(c1, .[ 0 ], .FromStart | .FromEnd);
|
||||
Expect(ArrayEquals(c1, .[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(c2, .[ 1, 2, 3 ]));
|
||||
|
||||
d1 := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
d2 := ArrayTrim(d1, .[ 0, 0, 0 ], .FromStart | .MatchInFull);
|
||||
d3 := ArrayTrim(d1, .[ 0, 0, 0 ], .FromEnd | .MatchInFull);
|
||||
d4 := ArrayTrim(d1, .[ 0, 0, 0 ], .FromStart | .FromEnd | .MatchInFull);
|
||||
Expect(ArrayEquals(d1, .[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(d2, .[ 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(d3, .[ 0, 0, 0, 1, 2, 3 ]));
|
||||
Expect(ArrayEquals(d4, .[ 1, 2, 3 ]));
|
||||
});
|
||||
}
|
||||
|
|
@ -192,50 +192,3 @@ range_of :: ($T: Type, loc := #caller_location) -> (T, T) #expand {
|
|||
return min_of(T, loc = loc), max_of(T, loc = loc);
|
||||
}
|
||||
|
||||
|
||||
#scope_file
|
||||
|
||||
#if RunTests #run {
|
||||
Test("min_of/max_of:enums", t => {
|
||||
U8Enum :: enum u8 { lo :: -1; hi :: +1; }
|
||||
S8Enum :: enum s8 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U8Enum) == U8Enum.lo);
|
||||
Expect(min_of(S8Enum) == S8Enum.lo);
|
||||
Expect(max_of(U8Enum) == U8Enum.hi);
|
||||
Expect(max_of(S8Enum) == S8Enum.hi);
|
||||
}
|
||||
|
||||
U16Enum :: enum u16 { lo :: -1; hi :: +1; }
|
||||
S16Enum :: enum s16 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U16Enum) == U16Enum.lo);
|
||||
Expect(min_of(S16Enum) == S16Enum.lo);
|
||||
Expect(max_of(U16Enum) == U16Enum.hi);
|
||||
Expect(max_of(S16Enum) == S16Enum.hi);
|
||||
}
|
||||
|
||||
U32Enum :: enum u32 { lo :: -1; hi :: +1; }
|
||||
S32Enum :: enum s32 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U32Enum) == U32Enum.lo);
|
||||
Expect(min_of(S32Enum) == S32Enum.lo);
|
||||
Expect(max_of(U32Enum) == U32Enum.hi);
|
||||
Expect(max_of(S32Enum) == S32Enum.hi);
|
||||
}
|
||||
|
||||
U64Enum :: enum u64 { lo :: -1; hi :: +1; }
|
||||
S64Enum :: enum s64 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U64Enum) == U64Enum.lo);
|
||||
Expect(min_of(S64Enum) == S64Enum.lo);
|
||||
Expect(max_of(U64Enum) == U64Enum.hi);
|
||||
Expect(max_of(S64Enum) == S64Enum.hi);
|
||||
}
|
||||
|
||||
// @note(judah): just making sure this compiles
|
||||
lo, hi := range_of(U64Enum);
|
||||
Expect(lo == U64Enum.lo);
|
||||
Expect(hi == U64Enum.hi);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,57 +120,3 @@ LazyInit :: inline (t: *Map) {
|
|||
TrySetAllocator(*t.free_slots);
|
||||
}
|
||||
|
||||
|
||||
#if RunTests #run {
|
||||
Test("map:basic operations", t => {
|
||||
ITERATIONS :: 64;
|
||||
|
||||
values: Map(int, int);
|
||||
for 0..ITERATIONS {
|
||||
MapSet(*values, it, it * it);
|
||||
}
|
||||
|
||||
for 0..ITERATIONS {
|
||||
v, ok := MapGet(*values, it);
|
||||
Expect(v == it * it);
|
||||
}
|
||||
|
||||
for 0..ITERATIONS if it % 2 == 0 {
|
||||
ok := MapRemove(*values, it);
|
||||
Expect(ok);
|
||||
}
|
||||
|
||||
for 0..ITERATIONS if it % 2 == 0 {
|
||||
_, ok := MapGet(*values, it);
|
||||
Expect(!ok);
|
||||
}
|
||||
});
|
||||
|
||||
Test("map:free slots", t => {
|
||||
values: Map(int, int);
|
||||
|
||||
MapSet(*values, 1, 100);
|
||||
MapSet(*values, 2, 200);
|
||||
MapSet(*values, 3, 300);
|
||||
Expect(values.count == 3);
|
||||
Expect(values.slots.allocated == values.AllocatedItemsAtStart);
|
||||
|
||||
// deleting something that doesn't exist should do nothing
|
||||
ok := MapRemove(*values, 0);
|
||||
Expect(!ok);
|
||||
Expect(values.count == 3);
|
||||
|
||||
MapRemove(*values, 2);
|
||||
Expect(values.count == 2);
|
||||
});
|
||||
|
||||
Test("map:iteration", t => {
|
||||
values: Map(int, int);
|
||||
|
||||
for 0..10 MapSet(*values, it, it * it);
|
||||
Expect(values.count == 11);
|
||||
|
||||
for v, k: values Expect(v == k * k);
|
||||
for < v, k: values Expect(v == k * k);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
185
+internal/tests/module.jai
Normal file
185
+internal/tests/module.jai
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
// @note(judah): these are put in a separate module to fix some weirdness with #module_parameters
|
||||
// when used in the test runner.
|
||||
|
||||
#import "jc";
|
||||
|
||||
#run,stallable {
|
||||
// arrays
|
||||
Test("slice", t => {
|
||||
a1 := int.[ 1, 2, 3, 4, 5 ];
|
||||
a2 := ArraySlice(a1, 2);
|
||||
Expect(a2.count == 3);
|
||||
Expect(ArrayEquals(a2, int.[ 3, 4, 5 ]));
|
||||
|
||||
b1 := int.[ 1, 2, 3, 4, 5 ];
|
||||
b2 := ArraySlice(b1, 2, 0);
|
||||
Expect(b2.count == 0);
|
||||
Expect(b2.data == b1.data + 2);
|
||||
|
||||
c1 := int.[ 1, 2, 3, 4, 5 ];
|
||||
c2 := ArraySlice(c1, 3, 1);
|
||||
Expect(c2.count == 1);
|
||||
Expect(ArrayEquals(c2, int.[ 4 ]));
|
||||
|
||||
d1 := int.[ 1, 2, 3 ];
|
||||
d2 := ArraySlice(d1, 2);
|
||||
Expect(d2.count == 1);
|
||||
Expect(ArrayEquals(d2, int.[ 3 ]));
|
||||
});
|
||||
|
||||
Test("find", t => {
|
||||
a := int.[ 1, 2, 3, 4, 5 ];
|
||||
|
||||
ok, res := ArrayFind(a, 3);
|
||||
Expect(ok && res.index == 2);
|
||||
Expect(res.value == 3);
|
||||
|
||||
ok, res = ArrayFind(a, -1);
|
||||
Expect(!ok && res.index == -1);
|
||||
|
||||
b := int.[ 1, 2, 2, 3, 4, 5, 2 ];
|
||||
|
||||
ok, res = ArrayFind(b, 2);
|
||||
Expect(ok && res.index == 1);
|
||||
|
||||
ok, res = ArrayFind(b, 2, .FromEnd);
|
||||
Expect(ok && res.index == 6);
|
||||
|
||||
c := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
|
||||
ok, res = ArrayFind(c, 0, .Last);
|
||||
Expect(ok && res.index == 8);
|
||||
|
||||
ok, res = ArrayFind(c, 0, .FromEnd | .Last);
|
||||
Expect(ok && res.index == 0);
|
||||
});
|
||||
|
||||
Test("contains", t => {
|
||||
a := int.[ 1, 2, 3, 4, 5 ];
|
||||
Expect(ArrayContains(a, 3));
|
||||
Expect(!ArrayContains(a, -1));
|
||||
});
|
||||
|
||||
Test("trim", t => {
|
||||
a1 := int.[ 0, 0, 0, 1, 2, 3 ];
|
||||
a2 := ArrayTrim(a1, .[ 0 ]);
|
||||
Expect(ArrayEquals(a1, .[ 0, 0, 0, 1, 2, 3 ]));
|
||||
Expect(ArrayEquals(a2, .[ 1, 2, 3 ]));
|
||||
|
||||
b1 := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
b2 := ArrayTrim(b1, .[ 0 ], .FromEnd);
|
||||
Expect(ArrayEquals(b1, .[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(b2, .[ 0, 0, 0, 1, 2, 3 ]));
|
||||
|
||||
c1 := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
c2 := ArrayTrim(c1, .[ 0 ], .FromStart | .FromEnd);
|
||||
Expect(ArrayEquals(c1, .[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(c2, .[ 1, 2, 3 ]));
|
||||
|
||||
d1 := int.[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ];
|
||||
d2 := ArrayTrim(d1, .[ 0, 0, 0 ], .FromStart | .MatchInFull);
|
||||
d3 := ArrayTrim(d1, .[ 0, 0, 0 ], .FromEnd | .MatchInFull);
|
||||
d4 := ArrayTrim(d1, .[ 0, 0, 0 ], .FromStart | .FromEnd | .MatchInFull);
|
||||
Expect(ArrayEquals(d1, .[ 0, 0, 0, 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(d2, .[ 1, 2, 3, 0, 0, 0 ]));
|
||||
Expect(ArrayEquals(d3, .[ 0, 0, 0, 1, 2, 3 ]));
|
||||
Expect(ArrayEquals(d4, .[ 1, 2, 3 ]));
|
||||
});
|
||||
|
||||
// type_info
|
||||
Test("min_of/max_of:enums", t => {
|
||||
U8Enum :: enum u8 { lo :: -1; hi :: +1; }
|
||||
S8Enum :: enum s8 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U8Enum) == U8Enum.lo);
|
||||
Expect(min_of(S8Enum) == S8Enum.lo);
|
||||
Expect(max_of(U8Enum) == U8Enum.hi);
|
||||
Expect(max_of(S8Enum) == S8Enum.hi);
|
||||
}
|
||||
|
||||
U16Enum :: enum u16 { lo :: -1; hi :: +1; }
|
||||
S16Enum :: enum s16 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U16Enum) == U16Enum.lo);
|
||||
Expect(min_of(S16Enum) == S16Enum.lo);
|
||||
Expect(max_of(U16Enum) == U16Enum.hi);
|
||||
Expect(max_of(S16Enum) == S16Enum.hi);
|
||||
}
|
||||
|
||||
U32Enum :: enum u32 { lo :: -1; hi :: +1; }
|
||||
S32Enum :: enum s32 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U32Enum) == U32Enum.lo);
|
||||
Expect(min_of(S32Enum) == S32Enum.lo);
|
||||
Expect(max_of(U32Enum) == U32Enum.hi);
|
||||
Expect(max_of(S32Enum) == S32Enum.hi);
|
||||
}
|
||||
|
||||
U64Enum :: enum u64 { lo :: -1; hi :: +1; }
|
||||
S64Enum :: enum s64 { lo :: -2; hi :: -1; }
|
||||
{
|
||||
Expect(min_of(U64Enum) == U64Enum.lo);
|
||||
Expect(min_of(S64Enum) == S64Enum.lo);
|
||||
Expect(max_of(U64Enum) == U64Enum.hi);
|
||||
Expect(max_of(S64Enum) == S64Enum.hi);
|
||||
}
|
||||
|
||||
// @note(judah): just making sure this compiles
|
||||
lo, hi := range_of(U64Enum);
|
||||
Expect(lo == U64Enum.lo);
|
||||
Expect(hi == U64Enum.hi);
|
||||
});
|
||||
|
||||
// map
|
||||
Test("map:basic operations", t => {
|
||||
ITERATIONS :: 64;
|
||||
|
||||
values: Map(int, int);
|
||||
for 0..ITERATIONS {
|
||||
MapSet(*values, it, it * it);
|
||||
}
|
||||
|
||||
for 0..ITERATIONS {
|
||||
v, ok := MapGet(*values, it);
|
||||
Expect(v == it * it);
|
||||
}
|
||||
|
||||
for 0..ITERATIONS if it % 2 == 0 {
|
||||
ok := MapRemove(*values, it);
|
||||
Expect(ok);
|
||||
}
|
||||
|
||||
for 0..ITERATIONS if it % 2 == 0 {
|
||||
_, ok := MapGet(*values, it);
|
||||
Expect(!ok);
|
||||
}
|
||||
});
|
||||
|
||||
Test("map:free slots", t => {
|
||||
values: Map(int, int);
|
||||
|
||||
MapSet(*values, 1, 100);
|
||||
MapSet(*values, 2, 200);
|
||||
MapSet(*values, 3, 300);
|
||||
Expect(values.count == 3);
|
||||
Expect(values.slots.allocated == values.AllocatedItemsAtStart);
|
||||
|
||||
// deleting something that doesn't exist should do nothing
|
||||
ok := MapRemove(*values, 0);
|
||||
Expect(!ok);
|
||||
Expect(values.count == 3);
|
||||
|
||||
MapRemove(*values, 2);
|
||||
Expect(values.count == 2);
|
||||
});
|
||||
|
||||
Test("map:iteration", t => {
|
||||
values: Map(int, int);
|
||||
|
||||
for 0..10 MapSet(*values, it, it * it);
|
||||
Expect(values.count == 11);
|
||||
|
||||
for v, k: values Expect(v == k * k);
|
||||
for < v, k: values Expect(v == k * k);
|
||||
});
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
compiler :: #import "Compiler";
|
||||
compiler.set_build_options_dc(.{ do_output = false });
|
||||
|
||||
_ :: #import "jc"(true);
|
||||
_ :: #import "jc";
|
||||
_ :: #import "jc/+internal/tests";
|
||||
_ :: #import "jc/math"(RUN_TESTS = true);
|
||||
_ :: #import "jc/fmt/base64"(true);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,14 +5,13 @@
|
|||
/// Additionally, it provides a platform-independant
|
||||
/// interface for interacting with the target operating
|
||||
/// system.
|
||||
#module_parameters(RunTests := false);
|
||||
|
||||
#load "+internal/builtin.jai";
|
||||
#load "+internal/array.jai";
|
||||
#load "+internal/arenas.jai";
|
||||
#load "+internal/memory.jai";
|
||||
#load "+internal/arrays.jai";
|
||||
#load "+internal/map.jai";
|
||||
#load "+internal/hashing.jai";
|
||||
#load "+internal/memory.jai";
|
||||
#load "+internal/arenas.jai";
|
||||
#load "+internal/testing.jai";
|
||||
#load "+internal/keywords.jai";
|
||||
#load "+internal/type_info.jai";
|
||||
|
|
|
|||
Loading…
Reference in a new issue