mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-24 05:51:34 +00:00
[dynamic; N]T proof of concept: fixed capacity dynamic array (akin to small_array.Small_Array(N, T))
This commit is contained in:
145
src/types.cpp
145
src/types.cpp
@@ -248,6 +248,12 @@ struct TypeNamed {
|
||||
}) \
|
||||
TYPE_KIND(Slice, struct { Type *elem; }) \
|
||||
TYPE_KIND(DynamicArray, struct { Type *elem; }) \
|
||||
TYPE_KIND(FixedCapacityDynamicArray, struct { \
|
||||
i64 capacity; \
|
||||
Type *generic_capacity; \
|
||||
Type *elem; \
|
||||
i64 padding_needed; /*-1 if unknown*/ \
|
||||
}) \
|
||||
TYPE_KIND(Map, struct { \
|
||||
Type *key; \
|
||||
Type *value; \
|
||||
@@ -378,6 +384,7 @@ enum Typeid_Kind : u8 {
|
||||
Typeid_Matrix,
|
||||
Typeid_SoaPointer,
|
||||
Typeid_Bit_Field,
|
||||
Typeid_Fixed_Capacity_Dynamic_Array,
|
||||
|
||||
Typeid__COUNT
|
||||
|
||||
@@ -698,6 +705,7 @@ gb_global Type *t_type_info_simd_vector = nullptr;
|
||||
gb_global Type *t_type_info_matrix = nullptr;
|
||||
gb_global Type *t_type_info_soa_pointer = nullptr;
|
||||
gb_global Type *t_type_info_bit_field = nullptr;
|
||||
gb_global Type *t_type_info_fixed_capacity_dynamic_array = nullptr;
|
||||
|
||||
gb_global Type *t_type_info_named_ptr = nullptr;
|
||||
gb_global Type *t_type_info_integer_ptr = nullptr;
|
||||
@@ -726,6 +734,7 @@ gb_global Type *t_type_info_simd_vector_ptr = nullptr;
|
||||
gb_global Type *t_type_info_matrix_ptr = nullptr;
|
||||
gb_global Type *t_type_info_soa_pointer_ptr = nullptr;
|
||||
gb_global Type *t_type_info_bit_field_ptr = nullptr;
|
||||
gb_global Type *t_type_info_fixed_capacity_dynamic_array_ptr = nullptr;
|
||||
|
||||
gb_global Type *t_allocator = nullptr;
|
||||
gb_global Type *t_allocator_ptr = nullptr;
|
||||
@@ -1094,6 +1103,23 @@ gb_internal Type *alloc_type_dynamic_array(Type *elem) {
|
||||
return t;
|
||||
}
|
||||
|
||||
gb_internal Type *alloc_type_fixed_capacity_dynamic_array(Type *elem, i64 capacity, Type *generic_capacity = nullptr) {
|
||||
if (generic_capacity != nullptr) {
|
||||
Type *t = alloc_type(Type_FixedCapacityDynamicArray);
|
||||
t->FixedCapacityDynamicArray.elem = elem;
|
||||
t->FixedCapacityDynamicArray.capacity = capacity;
|
||||
t->FixedCapacityDynamicArray.generic_capacity = generic_capacity;
|
||||
t->FixedCapacityDynamicArray.padding_needed = 0;
|
||||
return t;
|
||||
}
|
||||
Type *t = alloc_type(Type_FixedCapacityDynamicArray);
|
||||
t->FixedCapacityDynamicArray.elem = elem;
|
||||
t->FixedCapacityDynamicArray.capacity = capacity;
|
||||
t->FixedCapacityDynamicArray.padding_needed = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_internal Type *alloc_type_struct() {
|
||||
Type *t = alloc_type(Type_Struct);
|
||||
@@ -1658,6 +1684,11 @@ gb_internal bool is_type_dynamic_array(Type *t) {
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_DynamicArray;
|
||||
}
|
||||
gb_internal bool is_type_fixed_capacity_dynamic_array(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_FixedCapacityDynamicArray;
|
||||
}
|
||||
gb_internal bool is_type_slice(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
@@ -1687,6 +1718,8 @@ gb_internal Type *base_array_type(Type *t) {
|
||||
return bt->EnumeratedArray.elem;
|
||||
} else if (is_type_simd_vector(bt)) {
|
||||
return bt->SimdVector.elem;
|
||||
} else if (is_type_fixed_capacity_dynamic_array(bt)) {
|
||||
return bt->FixedCapacityDynamicArray.elem;
|
||||
} else if (is_type_matrix(bt)) {
|
||||
return bt->Matrix.elem;
|
||||
}
|
||||
@@ -1702,6 +1735,8 @@ gb_internal Type *base_any_array_type(Type *t) {
|
||||
return bt->Slice.elem;
|
||||
} else if (is_type_dynamic_array(bt)) {
|
||||
return bt->DynamicArray.elem;
|
||||
} else if (is_type_fixed_capacity_dynamic_array(bt)) {
|
||||
return bt->FixedCapacityDynamicArray.elem;
|
||||
} else if (is_type_enumerated_array(bt)) {
|
||||
return bt->EnumeratedArray.elem;
|
||||
} else if (is_type_simd_vector(bt)) {
|
||||
@@ -2234,6 +2269,7 @@ gb_internal bool is_type_indexable(Type *t) {
|
||||
case Type_Array:
|
||||
case Type_Slice:
|
||||
case Type_DynamicArray:
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
case Type_Map:
|
||||
return true;
|
||||
case Type_MultiPointer:
|
||||
@@ -2254,6 +2290,7 @@ gb_internal bool is_type_sliceable(Type *t) {
|
||||
case Type_Array:
|
||||
case Type_Slice:
|
||||
case Type_DynamicArray:
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
return true;
|
||||
case Type_EnumeratedArray:
|
||||
return false;
|
||||
@@ -2394,6 +2431,11 @@ gb_internal bool is_type_polymorphic(Type *t, bool or_specialized=false) {
|
||||
return is_type_polymorphic(t->SimdVector.elem, or_specialized);
|
||||
case Type_DynamicArray:
|
||||
return is_type_polymorphic(t->DynamicArray.elem, or_specialized);
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
if (t->FixedCapacityDynamicArray.generic_capacity != nullptr) {
|
||||
return true;
|
||||
}
|
||||
return is_type_polymorphic(t->FixedCapacityDynamicArray.elem, or_specialized);
|
||||
case Type_Slice:
|
||||
return is_type_polymorphic(t->Slice.elem, or_specialized);
|
||||
|
||||
@@ -2515,6 +2557,11 @@ gb_internal bool type_has_nil(Type *t) {
|
||||
case Type_DynamicArray:
|
||||
case Type_Map:
|
||||
return true;
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
// TODO(bill): should it have `nil`?
|
||||
return false;
|
||||
|
||||
case Type_Union:
|
||||
return t->Union.kind != UnionType_no_nil;
|
||||
case Type_Struct:
|
||||
@@ -2642,6 +2689,9 @@ gb_internal bool is_type_comparable(Type *t) {
|
||||
case Type_Matrix:
|
||||
return is_type_comparable(t->Matrix.elem);
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
return false;
|
||||
|
||||
case Type_BitSet:
|
||||
return true;
|
||||
|
||||
@@ -2688,6 +2738,10 @@ gb_internal bool is_type_simple_compare(Type *t) {
|
||||
case Type_EnumeratedArray:
|
||||
return is_type_simple_compare(t->EnumeratedArray.elem);
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
return false;
|
||||
// return is_type_simple_compare(t->FixedCapacityDynamicArray.elem);
|
||||
|
||||
case Type_Basic:
|
||||
if (t->Basic.flags & BasicFlag_SimpleCompare) {
|
||||
return true;
|
||||
@@ -2758,6 +2812,10 @@ gb_internal bool is_type_nearly_simple_compare(Type *t) {
|
||||
case Type_EnumeratedArray:
|
||||
return is_type_nearly_simple_compare(t->EnumeratedArray.elem);
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
return false;
|
||||
// return is_type_nearly_simple_compare(t->FixedCapacityDynamicArray.elem);
|
||||
|
||||
case Type_Basic:
|
||||
if (t->Basic.flags & (BasicFlag_SimpleCompare|BasicFlag_Numeric)) {
|
||||
return true;
|
||||
@@ -2838,6 +2896,7 @@ gb_internal bool is_type_load_safe(Type *type) {
|
||||
case Type_DynamicArray:
|
||||
case Type_Proc:
|
||||
case Type_SoaPointer:
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
return false;
|
||||
|
||||
case Type_Enum:
|
||||
@@ -3047,6 +3106,10 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple
|
||||
case Type_DynamicArray:
|
||||
return are_types_identical(x->DynamicArray.elem, y->DynamicArray.elem);
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
return (x->FixedCapacityDynamicArray.capacity == y->FixedCapacityDynamicArray.capacity) &&
|
||||
are_types_identical(x->FixedCapacityDynamicArray.elem, y->FixedCapacityDynamicArray.elem);
|
||||
|
||||
case Type_Slice:
|
||||
return are_types_identical(x->Slice.elem, y->Slice.elem);
|
||||
|
||||
@@ -4144,9 +4207,22 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
}
|
||||
|
||||
case Type_DynamicArray:
|
||||
// data, count, capacity, allocator
|
||||
// data, len, cap, allocator
|
||||
return build_context.int_size;
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
// data, len
|
||||
{
|
||||
Type *elem = t->FixedCapacityDynamicArray.elem;
|
||||
bool pop = type_path_push(path, elem);
|
||||
if (path->failure) {
|
||||
return FAILURE_ALIGNMENT;
|
||||
}
|
||||
i64 align = type_align_of_internal(elem, path);
|
||||
if (pop) type_path_pop(path);
|
||||
return gb_max(build_context.int_size, align);
|
||||
}
|
||||
|
||||
case Type_Slice:
|
||||
return build_context.int_size;
|
||||
|
||||
@@ -4419,6 +4495,34 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
// data + len + cap + allocator(procedure+data)
|
||||
return 3*build_context.int_size + 2*build_context.ptr_size;
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
{
|
||||
// data + len
|
||||
i64 capacity = t->FixedCapacityDynamicArray.capacity;
|
||||
Type *elem = t->FixedCapacityDynamicArray.elem;
|
||||
i64 align = type_align_of_internal(elem, path);
|
||||
if (path->failure) {
|
||||
return FAILURE_SIZE;
|
||||
}
|
||||
align = gb_max(build_context.int_size, align);
|
||||
|
||||
i64 size = type_size_of(elem);
|
||||
size *= capacity;
|
||||
|
||||
i64 old_size = size;
|
||||
size = align_formula(size, build_context.int_size);
|
||||
|
||||
i64 padding = size - old_size;
|
||||
if (t->FixedCapacityDynamicArray.padding_needed >= 0) {
|
||||
GB_ASSERT(t->FixedCapacityDynamicArray.padding_needed == padding);
|
||||
}
|
||||
t->FixedCapacityDynamicArray.padding_needed = padding;
|
||||
|
||||
size += 1*build_context.int_size;
|
||||
size = align_formula(size, align);
|
||||
return size;
|
||||
}
|
||||
|
||||
case Type_Map:
|
||||
/*
|
||||
struct {
|
||||
@@ -4644,6 +4748,23 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) {
|
||||
return 3*build_context.int_size; // allocator
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
switch (index) {
|
||||
case 0:
|
||||
if (field_type_) *field_type_ = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity);
|
||||
return 0; // data
|
||||
|
||||
case 1: // len
|
||||
if (field_type_) *field_type_ = t_int;
|
||||
{
|
||||
i64 offset = 0;
|
||||
offset = type_size_of(alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity));
|
||||
offset = align_formula(offset, build_context.int_size);
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type_Union:
|
||||
if (!is_type_union_maybe_pointer(t)) {
|
||||
/* i64 s = */ type_size_of(t);
|
||||
@@ -4711,6 +4832,12 @@ gb_internal i64 type_offset_of_from_selection(Type *type, Selection sel) {
|
||||
case 3: t = t_allocator; break;
|
||||
}
|
||||
break;
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
switch (index) {
|
||||
case 0: t = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity); break;
|
||||
case 1: t = t_int; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4970,6 +5097,15 @@ gb_internal Type *type_internal_index(Type *t, isize index) {
|
||||
default: GB_PANIC("invalid raw dynamic array index");
|
||||
};
|
||||
}
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
{
|
||||
switch (index) {
|
||||
case 0: t = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity); break;
|
||||
case 1: return t_int;
|
||||
default: GB_PANIC("invalid raw fixed capacity dynamic array index");
|
||||
};
|
||||
}
|
||||
case Type_Struct:
|
||||
return get_struct_field_type(bt, index);
|
||||
case Type_Union:
|
||||
@@ -5068,6 +5204,13 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
|
||||
str = write_type_to_string(str, type->DynamicArray.elem, shorthand, allow_polymorphic);
|
||||
break;
|
||||
|
||||
case Type_FixedCapacityDynamicArray:
|
||||
str = gb_string_appendc(str, "[dynamic; ");
|
||||
str = gb_string_appendc(str, gb_bprintf("%lld", cast(long long)type->FixedCapacityDynamicArray.capacity));
|
||||
str = gb_string_appendc(str, "]");
|
||||
str = write_type_to_string(str, type->FixedCapacityDynamicArray.elem, shorthand, allow_polymorphic);
|
||||
break;
|
||||
|
||||
case Type_Enum:
|
||||
str = gb_string_appendc(str, "enum");
|
||||
if (type->Enum.base_type != nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user