// ---------------------------------
// Dynamic Arrays
// ---------------------------------
-make :: ($T: type_expr, initial_cap := 4) -> [..] T {
+make :: ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T {
arr : [..] T;
- init(^arr, initial_cap);
+ init(^arr, capacity, allocator);
return arr;
}
-init :: (arr: ^[..] $T, initial_cap := 4) {
+init :: (arr: ^[..] $T, capacity := 4, allocator := context.allocator) {
arr.count = 0;
- arr.capacity = initial_cap;
- arr.data = calloc(sizeof T * arr.capacity);
+ arr.capacity = capacity;
+ arr.allocator = allocator;
+ arr.data = raw_alloc(allocator, sizeof T * arr.capacity);
}
free :: (arr: ^[..] $T) {
arr.count = 0;
arr.capacity = 0;
- cfree(arr.data);
+ raw_free(arr.allocator, arr.data);
arr.data = null;
}
-copy :: (arr: ^[..] $T) -> [..] T {
+copy :: (arr: ^[..] $T, allocator := context.allocator) -> [..] T {
new_arr : [..] T;
- init(^new_arr, arr.count);
+ init(^new_arr, arr.count, allocator);
new_arr.count = arr.count;
for i: 0 .. arr.count do new_arr.data[i] = arr.data[i];
return new_arr;
}
-copy_range :: (arr: ^[..] $T, r: range) -> [..] T {
+copy_range :: (arr: ^[..] $T, r: range, allocator := context.allocator) -> [..] T {
new_arr : [..] T;
- init(^new_arr, r.high - r.low);
+ init(^new_arr, r.high - r.low, allocator);
new_arr.count = r.high - r.low;
for i: r do new_arr.data[i] = arr.data[i];
arr.count = 0;
}
-ensure_capacity :: (arr: ^[..] $T, cap: u32) -> bool {
- if arr.capacity >= cap do return true;
+ensure_capacity :: (arr: ^[..] $T, capacity: u32) -> bool {
+ if arr.capacity >= capacity do return true;
- while cap > arr.capacity do arr.capacity <<= 1;
- new_data := cresize(arr.data, sizeof T * arr.capacity);
+ while capacity > arr.capacity do arr.capacity <<= 1;
+ new_data := raw_resize(arr.allocator, arr.data, sizeof T * arr.capacity);
if new_data == null do return false;
arr.data = new_data;
return true;
curr_pos : i32;
data : [..] u8;
- alloc : Allocator;
}
dynamic_string_stream_make :: (init_size := 128, a := context.allocator) -> DynamicStringStream {
data : [..] u8;
- array.init(^data, init_size);
+ array.init(^data, init_size, allocator=a);
return DynamicStringStream.{
stream = Stream.{
curr_pos = 0,
data = data,
- alloc = a,
};
}
}
if dest >= data.count {
- #context_scope {
- context.allocator = alloc;
- if !array.ensure_capacity(^data, dest) do return Error.OutOfBounds;
- }
+ if !array.ensure_capacity(^data, dest) do return Error.OutOfBounds;
}
curr_pos = dest;
write = (use dss: ^DynamicStringStream, buffer: [] u8) -> (Error, u32) {
if curr_pos + buffer.count >= data.capacity {
- #context_scope {
- context.allocator = alloc;
- if !array.ensure_capacity(^data, curr_pos + buffer.count) do return Error.EOF, 0;
- }
+ if !array.ensure_capacity(^data, curr_pos + buffer.count) do return Error.EOF, 0;
}
memory.copy(^data.data[curr_pos], buffer.data, buffer.count);
write_at = (use dss: ^DynamicStringStream, at: u32, buffer: [] u8) -> (Error, u32) {
if at + buffer.count >= data.capacity {
- #context_scope {
- context.allocator = alloc;
- if !array.ensure_capacity(^data, at + buffer.count) do return Error.EOF, 0;
- }
+ if !array.ensure_capacity(^data, at + buffer.count) do return Error.EOF, 0;
}
memory.copy(^data.data[at], buffer.data, buffer.count);
},
write_byte = (use dss: ^DynamicStringStream, byte: u8) -> Error {
- #context_scope {
- context.allocator = alloc;
- if !array.ensure_capacity(^data, data.count + 1) do return Error.EOF;
- }
+ if !array.ensure_capacity(^data, data.count + 1) do return Error.EOF;
data[curr_pos] = byte;
curr_pos += 1;
use package core.conv as conv
Builder :: struct {
- alloc : Allocator;
data : [..] u8;
}
make :: proc (initial_cap := 4, alloc := context.allocator) -> Builder {
builder : Builder;
- builder.alloc = alloc;
-
- #context_scope {
- context.allocator = alloc;
- array.init(^builder.data, initial_cap);
- }
+ array.init(^builder.data, initial_cap, allocator = alloc);
return builder;
}
add_str :: proc (use sb: ^Builder, s: str) -> ^Builder {
len_total := data.count + s.count;
- if data.capacity < len_total do #context_scope {
- context.allocator = alloc;
+ if data.capacity < len_total {
if !array.ensure_capacity(^data, len_total) do return sb;
}
extern AstType *builtin_vararg_type;
extern Type *builtin_vararg_type_type;
extern AstTyped *builtin_context_variable;
+extern AstType *builtin_allocator_type;
typedef struct BuiltinSymbol {
char* package;
AstType *builtin_vararg_type;
Type *builtin_vararg_type_type;
AstTyped *builtin_context_variable;
+AstType *builtin_allocator_type;
const BuiltinSymbol builtin_symbols[] = {
{ NULL, "void", (AstNode *) &basic_type_void },
return;
}
+ builtin_allocator_type = (AstType *) symbol_raw_resolve(p->scope, "Allocator");
+ if (builtin_allocator_type == NULL) {
+ onyx_report_error((OnyxFilePos) { 0 }, "'Allocator' struct not found in builtin package.");
+ return;
+ }
+
fori (i, 0, Binary_Op_Count) {
bh_arr_new(global_heap_allocator, operator_overloads[i], 4);
}
case Type_Kind_Enum: return type_size_of(type->Enum.backing);
case Type_Kind_Slice: return 16; // HACK: These should not have to be 16 bytes in size, they should only have to be 12,
case Type_Kind_VarArgs: return 16; // but there are alignment issues right now with that so I decided to not fight it and just make them 16 bytes in size.
- case Type_Kind_DynArray: return 16;
+ case Type_Kind_DynArray: return 32; // data (8), count (4), capacity (4), allocator { func (4), ---(4), data (8) }
case Type_Kind_Compound: return type->Compound.size;
default: return 0;
}
return 2;
}
+static const StructMember slice_members[] = {
+ { 0, 0, NULL, "data", NULL, 0, 0 },
+ { 8, 1, &basic_types[Basic_Kind_U32], "count", NULL, 0, 0 },
+};
+
+static const StructMember array_members[] = {
+ { 0, 0, NULL, "data", NULL, 0, 0 },
+ { 8, 1, &basic_types[Basic_Kind_U32], "count", NULL, 0, 0 },
+ { 12, 2, &basic_types[Basic_Kind_U32], "capacity", NULL, 0, 0 },
+ { 16, 3, NULL, "allocator", NULL, 0, 0 },
+};
+
b32 type_lookup_member(Type* type, char* member, StructMember* smem) {
if (type->kind == Type_Kind_Pointer) type = type->Pointer.elem;
- smem->initial_value = NULL;
- smem->included_through_use = 0;
-
switch (type->kind) {
case Type_Kind_Struct: {
TypeStruct* stype = &type->Struct;
case Type_Kind_VarArgs:
case Type_Kind_Slice: {
- if (strcmp(member, "data") == 0) {
- smem->idx = 0;
- smem->offset = 0;
- smem->type = type->Slice.ptr_to_data;
- smem->name = "data";
- return 1;
- }
- if (strcmp(member, "count") == 0) {
- smem->idx = 1;
- smem->offset = 8;
- smem->type = &basic_types[Basic_Kind_U32];
- smem->name = "count";
- return 1;
- }
+ fori (i, 0, (i64) (sizeof(slice_members) / sizeof(StructMember))) {
+ if (strcmp(slice_members[i].name, member) == 0) {
+ *smem = slice_members[i];
+ if (smem->idx == 0) smem->type = type->Slice.ptr_to_data;
+ return 1;
+ }
+ }
return 0;
}
case Type_Kind_DynArray: {
- if (strcmp(member, "data") == 0) {
- smem->idx = 0;
- smem->offset = 0;
- smem->type = type->DynArray.ptr_to_data;
- smem->name = "data";
- return 1;
- }
- if (strcmp(member, "count") == 0) {
- smem->idx = 1;
- smem->offset = 8;
- smem->type = &basic_types[Basic_Kind_U32];
- smem->name = "count";
- return 1;
- }
- if (strcmp(member, "capacity") == 0) {
- smem->idx = 2;
- smem->offset = 12;
- smem->type = &basic_types[Basic_Kind_U32];
- smem->name = "capacity";
- return 1;
+ fori (i, 0, (i64) (sizeof(array_members) / sizeof(StructMember))) {
+ if (strcmp(array_members[i].name, member) == 0) {
+ *smem = array_members[i];
+ if (smem->idx == 0) smem->type = type->DynArray.ptr_to_data;
+ if (smem->idx == 3) smem->type = type_build_from_ast(context.ast_alloc, builtin_allocator_type);
+
+ return 1;
+ }
}
+ return 0;
}
default: return 0;
// are identical. - brendanfh 2020/09/07
case Type_Kind_VarArgs:
case Type_Kind_Slice: {
- if (idx == 0) {
- smem->idx = 0;
- smem->offset = 0;
- smem->type = type->Slice.ptr_to_data;
- smem->name = "data";
- return 1;
- }
- if (idx == 1) {
- smem->idx = 1;
- smem->offset = 8;
- smem->type = &basic_types[Basic_Kind_U32];
- smem->name = "count";
- return 1;
- }
+ if (idx > 2) return 0;
- return 0;
+ *smem = slice_members[idx];
+ if (smem->idx == 0) smem->type = type->Slice.ptr_to_data;
+
+ return 1;
}
case Type_Kind_DynArray: {
- if (idx == 0) {
- smem->idx = 0;
- smem->offset = 0;
- smem->type = type->DynArray.ptr_to_data;
- smem->name = "data";
- return 1;
- }
- if (idx == 1) {
- smem->idx = 1;
- smem->offset = 8;
- smem->type = &basic_types[Basic_Kind_U32];
- smem->name = "count";
- return 1;
- }
- if (idx == 2) {
- smem->idx = 2;
- smem->offset = 12;
- smem->type = &basic_types[Basic_Kind_U32];
- smem->name = "capacity";
- return 1;
- }
+ if (idx > 4) return 0;
+
+ *smem = array_members[idx];
+ if (idx == 0) smem->type = type->DynArray.ptr_to_data;
+ if (idx == 3) smem->type = type_build_from_ast(context.ast_alloc, builtin_allocator_type);
+
+ return 1;
}
default: return 0;
switch (type->kind) {
case Type_Kind_Slice:
case Type_Kind_VarArgs: return 2;
- case Type_Kind_DynArray: return 3;
+ case Type_Kind_DynArray: return 5;
case Type_Kind_Compound: return bh_arr_length(type->Compound.linear_members);
case Type_Kind_Struct: return bh_arr_length(type->Struct.linear_members);
default: return 0;
two->type = &basic_types[Basic_Kind_U32];
two->offset = 12;
}
+ if (idx == 3 || idx == 4) {
+ Type* allocator_type = type_build_from_ast(context.ast_alloc, builtin_allocator_type);
+ type_linear_member_lookup(allocator_type, idx - 3, two);
+ two->offset += 16;
+ }
return 1;
}
case Type_Kind_Struct: return type->Struct.mem_count;
case Type_Kind_Slice: return 2;
case Type_Kind_VarArgs: return 2;
- case Type_Kind_DynArray: return 3;
+ case Type_Kind_DynArray: return 4;
default: return 0;
}
}
case Type_Kind_Struct: return type_struct_is_simple(type);
case Type_Kind_Slice: return 1;
case Type_Kind_VarArgs: return 1;
- case Type_Kind_DynArray: return 1;
+ case Type_Kind_DynArray: return 0;
default: return 0;
}
}
switch (for_node->loop_type) {
case For_Loop_Range: emit_for_range(mod, &code, for_node, iter_local); break;
case For_Loop_Array: emit_for_array(mod, &code, for_node, iter_local); break;
- // NOTE: A dynamic array is just a slice with an extra capacity field on the end.
- // Just dropping the capacity field will mean we can just use the slice implementation.
+ // NOTE: A dynamic array is just a slice with a capacity and allocator on the end.
+ // Just dropping the extra fields will mean we can just use the slice implementation.
// - brendanfh 2020/09/04
- case For_Loop_DynArr: WI(WI_DROP);
+ // - brendanfh 2021/04/13
+ case For_Loop_DynArr: WI(WI_DROP); WI(WI_DROP); WI(WI_DROP);
case For_Loop_Slice: emit_for_slice(mod, &code, for_node, iter_local); break;
default: onyx_report_error(for_node->token->pos, "Invalid for loop type. You should probably not be seeing this...");
}
build_edges :: (tile: [] bool, a := context.allocator) -> [] u32 {
edges : [..] u32;
- #context_scope {
- context.allocator = a;
- array.init(^edges, 8);
- }
+ array.init(^edges, 8, allocator=a);
for y: u32.[0, 9] {
edge := 0;
Ingredient :: struct {
// This will just be a pointer into the file contents.
name : str = .{ null, 0 };
- appears_on : [..] u32 = .{ null, 0, 0 };
+ appears_on : [..] u32 = .{ null, 0, 0, .{ null, null_proc } };
allergen : str = .{ null, 0 };
}
Allergen :: struct {
name : str = .{ null, 0 };
- appears_on : [..] u32 = .{ null, 0, 0 };
+ appears_on : [..] u32 = .{ null, 0, 0, .{ null, null_proc } };
}
Food :: struct {