NODE(Type) \
NODE(BasicType) \
NODE(PointerType) \
+ NODE(MultiPointerType) \
NODE(FunctionType) \
NODE(ArrayType) \
NODE(SliceType) \
Ast_Kind_Type,
Ast_Kind_Basic_Type,
Ast_Kind_Pointer_Type,
+ Ast_Kind_Multi_Pointer_Type,
Ast_Kind_Function_Type,
Ast_Kind_Array_Type,
Ast_Kind_Slice_Type,
struct AstSliceType { AstType_base; AstType* elem; };
struct AstDynArrType { AstType_base; AstType* elem; };
struct AstVarArgType { AstType_base; AstType* elem; };
+struct AstMultiPointerType { AstType_base; AstType* elem; };
struct AstFunctionType {
AstType_base;
#define TYPE_KINDS \
TYPE_KIND(Basic, TypeBasic) \
- TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \
+ TYPE_KIND(Pointer, struct { \
+ TypeBasic base; \
+ Type *elem; \
+ }) \
+ TYPE_KIND(MultiPointer, struct { \
+ TypeBasic base; \
+ Type *elem; \
+ }) \
TYPE_KIND(Function, struct { \
Type *return_type; \
u16 param_count; \
Type* type_build_compound_type(bh_allocator alloc, struct AstCompound* compound);
Type* type_make_pointer(bh_allocator alloc, Type* to);
+Type* type_make_multi_pointer(bh_allocator alloc, Type* to);
Type* type_make_array(bh_allocator alloc, Type* to, u32 count);
Type* type_make_slice(bh_allocator alloc, Type* of);
Type* type_make_dynarray(bh_allocator alloc, Type* of);
b32 type_struct_is_simple(Type* type);
b32 type_is_pointer(Type* type);
+b32 type_is_multi_pointer(Type* type);
b32 type_is_rawptr(Type* type);
b32 type_is_array(Type* tyoe);
b32 type_is_struct(Type* type);
"TYPE",
"BASIC_TYPE",
"POINTER_TYPE",
+ "MULTI POINTER TYPE",
"FUNCTION_TYPE",
"ARRAY TYPE",
"SLICE TYPE",
AstTyped *node = *pnode;
if ((node->type->kind == Type_Kind_Basic && node->type->Basic.kind == Basic_Kind_Rawptr)
- || (node->type->kind == Type_Kind_Pointer)) {
+ || (node->type->kind == Type_Kind_Pointer)
+ || (node->type->kind == Type_Kind_MultiPointer)) {
AstNumLit *zero = make_int_literal(context.ast_alloc, 0);
zero->type = &basic_types[Basic_Kind_Rawptr];
enum BasicFlag effective_flags = 0;
switch (type->kind) {
- case Type_Kind_Basic: effective_flags = type->Basic.flags; break;
- case Type_Kind_Pointer: effective_flags = Basic_Flag_Pointer; break;
- case Type_Kind_Enum: effective_flags = Basic_Flag_Integer; break;
- case Type_Kind_Function: effective_flags = Basic_Flag_Equality; break;
+ case Type_Kind_Basic: effective_flags = type->Basic.flags; break;
+ case Type_Kind_Pointer: // nocheckin REMOVE THIS
+ case Type_Kind_MultiPointer: effective_flags = Basic_Flag_Pointer; break;
+ case Type_Kind_Enum: effective_flags = Basic_Flag_Integer; break;
+ case Type_Kind_Function: effective_flags = Basic_Flag_Equality; break;
}
return (binop_allowed[operation] & effective_flags) != 0;
}
// NOTE: Handle basic pointer math.
- if (type_is_pointer(binop->left->type)) {
+ if (type_is_multi_pointer(binop->left->type) || type_is_pointer(binop->left->type)) {
if (binop->operation != Binary_Op_Add && binop->operation != Binary_Op_Minus) goto bad_binaryop;
+ if (type_is_pointer(binop->left->type))
+ onyx_report_warning(binop->token->pos, "Doing pointer math on non-multi-pointer!");
+
resolve_expression_type(binop->right);
if (!type_is_integer(binop->right->type)) goto bad_binaryop;
- AstNumLit* numlit = make_int_literal(context.ast_alloc, type_size_of(binop->left->type->Pointer.elem));
+ AstNumLit* numlit = make_int_literal(context.ast_alloc, type_size_of(binop->left->type->MultiPointer.elem));
numlit->token = binop->right->token;
numlit->type = binop->right->type;
}
sl->flags |= Ast_Flag_Has_Been_Checked;
+ if (!type_is_ready_for_lookup(sl->type)) {
+ YIELD(sl->token->pos, "Waiting for structure type to be ready.");
+ }
+
AstTyped** actual = sl->args.values;
StructMember smem;
case Ast_Kind_Type: return sizeof(AstType);
case Ast_Kind_Basic_Type: return sizeof(AstBasicType);
case Ast_Kind_Pointer_Type: return sizeof(AstPointerType);
+ case Ast_Kind_Multi_Pointer_Type: return sizeof(AstMultiPointerType);
case Ast_Kind_Function_Type: return sizeof(AstFunctionType) + ((AstFunctionType *) node)->param_count * sizeof(AstType *);
case Ast_Kind_Array_Type: return sizeof(AstArrayType);
case Ast_Kind_Slice_Type: return sizeof(AstSliceType);
C(AstPointerType, elem);
break;
+ case Ast_Kind_Multi_Pointer_Type:
+ C(AstMultiPointerType, elem);
+ break;
+
case Ast_Kind_Array_Type:
C(AstArrayType, count_expr);
C(AstArrayType, elem);
new = make_node(AstSliceType, Ast_Kind_Slice_Type);
new->token = open_bracket;
+ } else if (parser->curr->type == '&' || parser->curr->type == '^') {
+ consume_token(parser);
+
+ new = make_node(AstMultiPointerType, Ast_Kind_Multi_Pointer_Type);
+ new->flags |= Basic_Flag_Pointer;
+ new->token = open_bracket;
+
} else if (parser->curr->type == Token_Type_Dot_Dot) {
new = make_node(AstDynArrType, Ast_Kind_DynArr_Type);
new->token = open_bracket;
break;
}
+ case Ast_Kind_Multi_Pointer_Type: {
+ if (elem.actual->kind != Type_Kind_MultiPointer) break;
+
+ bh_arr_push(elem_queue, ((PolySolveElem) {
+ .type_expr = ((AstMultiPointerType *) elem.type_expr)->elem,
+ .kind = PSK_Type,
+ .actual = elem.actual->MultiPointer.elem,
+ }));
+ break;
+ }
+
case Ast_Kind_Address_Of: {
if (elem.actual->kind != Type_Kind_Pointer) break;
case Ast_Kind_Slice_Type: SYMRES(type, &((AstSliceType *) *type)->elem); break;
case Ast_Kind_DynArr_Type: SYMRES(type, &((AstDynArrType *) *type)->elem); break;
case Ast_Kind_VarArg_Type: SYMRES(type, &((AstVarArgType *) *type)->elem); break;
+ case Ast_Kind_Multi_Pointer_Type: SYMRES(type, &((AstMultiPointerType *) *type)->elem); break;
case Ast_Kind_Function_Type: {
AstFunctionType* ftype = (AstFunctionType *) *type;
// TODO: Document this!!
bh_imap type_map;
static bh_imap type_pointer_map;
+static bh_imap type_multi_pointer_map;
static bh_imap type_array_map;
static bh_imap type_slice_map;
static bh_imap type_dynarr_map;
}
void types_init() {
- bh_imap_init(&type_map, global_heap_allocator, 255);
- bh_imap_init(&type_pointer_map, global_heap_allocator, 255);
- bh_imap_init(&type_array_map, global_heap_allocator, 255);
- bh_imap_init(&type_slice_map, global_heap_allocator, 255);
- bh_imap_init(&type_dynarr_map, global_heap_allocator, 255);
- bh_imap_init(&type_vararg_map, global_heap_allocator, 255);
+ bh_imap_init(&type_map, global_heap_allocator, 255);
+ bh_imap_init(&type_pointer_map, global_heap_allocator, 255);
+ bh_imap_init(&type_multi_pointer_map, global_heap_allocator, 255);
+ bh_imap_init(&type_array_map, global_heap_allocator, 255);
+ bh_imap_init(&type_slice_map, global_heap_allocator, 255);
+ bh_imap_init(&type_dynarr_map, global_heap_allocator, 255);
+ bh_imap_init(&type_vararg_map, global_heap_allocator, 255);
sh_new_arena(type_func_map);
fori (i, 0, Basic_Kind_Count) type_register(&basic_types[i]);
if (t1->Basic.kind == Basic_Kind_V128 || t2->Basic.kind == Basic_Kind_V128) return 1;
}
- if (t1->Basic.kind == Basic_Kind_Rawptr && type_is_pointer(t2)) {
+ if (t1->Basic.kind == Basic_Kind_Rawptr && (type_is_pointer(t2) || type_is_multi_pointer(t2))) {
return 1;
}
break;
break;
}
+ case Type_Kind_MultiPointer: {
+ // Multi-pointer decays to pointer
+ // [&] u8 -> &u8
+ if (t2->kind == Type_Kind_Pointer) {
+ if (!recurse_pointers) return 1;
+
+ if (types_are_compatible(t1->MultiPointer.elem, t2->Pointer.elem)) return 1;
+ }
+
+ // Multi-pointer decays to rawptr
+ if (t2->kind == Type_Kind_Basic && t2->Basic.kind == Basic_Kind_Rawptr) return 1;
+
+ break;
+ }
+
case Type_Kind_Array: {
if (t2->kind != Type_Kind_Array) return 0;
switch (type->kind) {
case Type_Kind_Basic: return type->Basic.size;
+ case Type_Kind_MultiPointer:
case Type_Kind_Pointer: return POINTER_SIZE;
case Type_Kind_Function: return 4;
case Type_Kind_Array: return type->Array.size;
switch (type->kind) {
case Type_Kind_Basic: return type->Basic.alignment;
+ case Type_Kind_MultiPointer:
case Type_Kind_Pointer: return POINTER_SIZE;
case Type_Kind_Function: return 4;
case Type_Kind_Array: return type_alignment_of(type->Array.elem);
return ptr_type;
}
+ case Ast_Kind_Multi_Pointer_Type: {
+ Type *inner_type = type_build_from_ast_inner(alloc, ((AstMultiPointerType *) type_node)->elem, 1);
+ Type *ptr_type = type_make_multi_pointer(alloc, inner_type);
+ if (ptr_type) ptr_type->ast_type = type_node;
+ return ptr_type;
+ }
+
case Ast_Kind_Function_Type: {
AstFunctionType* ftype_node = (AstFunctionType *) type_node;
u64 param_count = ftype_node->param_count;
}
}
+Type* type_make_multi_pointer(bh_allocator alloc, Type* to) {
+ if (to == NULL) return NULL;
+ if (to == (Type *) &node_that_signals_failure) return to;
+
+ assert(to->id > 0);
+ u64 ptr_id = bh_imap_get(&type_multi_pointer_map, to->id);
+ if (ptr_id > 0) {
+ Type* ptr_type = (Type *) bh_imap_get(&type_map, ptr_id);
+ return ptr_type;
+
+ } else {
+ Type* ptr_type = type_create(Type_Kind_MultiPointer, alloc, 0);
+ ptr_type->MultiPointer.base.flags |= Basic_Flag_Pointer;
+ ptr_type->MultiPointer.base.size = POINTER_SIZE;
+ ptr_type->MultiPointer.elem = to;
+
+ type_register(ptr_type);
+ bh_imap_put(&type_multi_pointer_map, to->id, ptr_type->id);
+
+ return ptr_type;
+ }
+}
+
Type* type_make_array(bh_allocator alloc, Type* to, u32 count) {
if (to == NULL) return NULL;
if (to == (Type *) &node_that_signals_failure) return to;
type_register(slice_type);
bh_imap_put(&type_slice_map, of->id, slice_type->id);
- type_make_pointer(alloc, of);
+ type_make_multi_pointer(alloc, of);
slice_type->Slice.elem = of;
return slice_type;
type_register(dynarr);
bh_imap_put(&type_dynarr_map, of->id, dynarr->id);
- type_make_pointer(alloc, of);
+ type_make_multi_pointer(alloc, of);
dynarr->DynArray.elem = of;
return dynarr;
type_register(va_type);
bh_imap_put(&type_vararg_map, of->id, va_type->id);
- type_make_pointer(alloc, of);
+ type_make_multi_pointer(alloc, of);
va_type->VarArgs.elem = of;
return va_type;
switch (type->kind) {
case Type_Kind_Basic: return type->Basic.name;
case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "&%s", type_get_unique_name(type->Pointer.elem));
+ case Type_Kind_MultiPointer: return bh_aprintf(global_scratch_allocator, "[&] %s", type_get_unique_name(type->Pointer.elem));
case Type_Kind_Array: return bh_aprintf(global_scratch_allocator, "[%d] %s", type->Array.count, type_get_unique_name(type->Array.elem));
case Type_Kind_Struct:
if (type->Struct.name)
switch (type->kind) {
case Type_Kind_Basic: return type->Basic.name;
case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "&%s", type_get_name(type->Pointer.elem));
+ case Type_Kind_MultiPointer: return bh_aprintf(global_scratch_allocator, "[&] %s", type_get_name(type->Pointer.elem));
case Type_Kind_Array: return bh_aprintf(global_scratch_allocator, "[%d] %s", type->Array.count, type_get_name(type->Array.elem));
case Type_Kind_PolyStruct:
Type* type_get_contained_type(Type* type) {
if (type == NULL) return NULL;
switch (type->kind) {
- case Type_Kind_Pointer: return type->Pointer.elem;
- case Type_Kind_Array: return type->Array.elem;
- case Type_Kind_Slice: return type->Slice.elem;
- case Type_Kind_DynArray: return type->DynArray.elem;
- case Type_Kind_VarArgs: return type->VarArgs.elem;
+ case Type_Kind_Pointer: return type->Pointer.elem;
+ case Type_Kind_MultiPointer: return type->MultiPointer.elem;
+ case Type_Kind_Array: return type->Array.elem;
+ case Type_Kind_Slice: return type->Slice.elem;
+ case Type_Kind_DynArray: return type->DynArray.elem;
+ case Type_Kind_VarArgs: return type->VarArgs.elem;
default: return NULL;
}
}
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_make_pointer(context.ast_alloc, type->Slice.elem);
+ if (smem->idx == 0) smem->type = type_make_multi_pointer(context.ast_alloc, type->Slice.elem);
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_make_pointer(context.ast_alloc, type->DynArray.elem);
+ if (smem->idx == 0) smem->type = type_make_multi_pointer(context.ast_alloc, type->DynArray.elem);
if (smem->idx == 3) smem->type = type_build_from_ast(context.ast_alloc, builtin_allocator_type);
return 1;
if (idx > 2) return 0;
*smem = slice_members[idx];
- if (smem->idx == 0) smem->type = type_make_pointer(context.ast_alloc, type->Slice.elem);
+ if (smem->idx == 0) smem->type = type_make_multi_pointer(context.ast_alloc, type->Slice.elem);
return 1;
}
if (idx > 4) return 0;
*smem = array_members[idx];
- if (idx == 0) smem->type = type_make_pointer(context.ast_alloc, type->DynArray.elem);
+ if (idx == 0) smem->type = type_make_multi_pointer(context.ast_alloc, type->DynArray.elem);
if (idx == 3) smem->type = type_build_from_ast(context.ast_alloc, builtin_allocator_type);
return 1;
case Type_Kind_Slice:
case Type_Kind_VarArgs: {
if (idx == 0) {
- two->type = type_make_pointer(context.ast_alloc, type->Slice.elem);
+ two->type = type_make_multi_pointer(context.ast_alloc, type->Slice.elem);
two->offset = 0;
}
if (idx == 1) {
}
case Type_Kind_DynArray: {
if (idx == 0) {
- two->type = type_make_pointer(context.ast_alloc, type->DynArray.elem);
+ two->type = type_make_multi_pointer(context.ast_alloc, type->DynArray.elem);
two->offset = 0;
}
if (idx == 1) {
return type->kind == Type_Kind_Pointer;
}
+b32 type_is_multi_pointer(Type* type) {
+ if (type == NULL) return 0;
+ return type->kind == Type_Kind_MultiPointer;
+}
+
b32 type_is_rawptr(Type* type) {
if (type == NULL) return 0;
return type->kind == Type_Kind_Basic && type->Basic.kind == Basic_Kind_Rawptr;
b32 type_is_array_accessible(Type* type) {
if (type == NULL) return 0;
- if (type_is_pointer(type)) return 1;
+ // if (type_is_pointer(type)) return 1;
+ if (type_is_multi_pointer(type)) return 1;
if (type->kind == Type_Kind_Array) return 1;
if (type->kind == Type_Kind_Slice) return 1;
if (type->kind == Type_Kind_DynArray) return 1;
if (type->kind == Type_Kind_Pointer) return WASM_TYPE_PTR;
if (type->kind == Type_Kind_Array) return WASM_TYPE_PTR;
if (type->kind == Type_Kind_Function) return WASM_TYPE_FUNC;
+ if (type->kind == Type_Kind_MultiPointer) return WASM_TYPE_PTR;
if (type->kind == Type_Kind_Basic) {
TypeBasic* basic = &type->Basic;
if (local->type->kind == Type_Kind_Enum && local->type->Enum.backing->kind == Type_Kind_Basic) return 1;
if (local->type->kind == Type_Kind_Distinct && local->type->Distinct.base_type->kind == Type_Kind_Basic) return 1;
if (local->type->kind == Type_Kind_Pointer) return 1;
+ if (local->type->kind == Type_Kind_MultiPointer) return 1;
return 0;
}
u32 alignment = type_get_alignment_log2(type);
i32 store_size = type_size_of(type);
- i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer;
+ i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer || type->kind == Type_Kind_MultiPointer;
if (is_basic && (type->Basic.flags & Basic_Flag_Pointer)) {
WID(NULL, WI_I32_STORE, ((WasmInstructionData) { 2, offset }));
assert(type);
i32 load_size = type_size_of(type);
- i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer;
+ i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer || type->kind == Type_Kind_MultiPointer;
WasmInstructionType instr = WI_NOP;
i32 alignment = type_get_alignment_log2(type);
}
if (source_expr->kind == Ast_Kind_Subscript
- && source_expr->type->kind != Type_Kind_Pointer) {
+ && source_expr->type->kind != Type_Kind_Pointer && source_expr->type->kind != Type_Kind_MultiPointer) {
u64 o2 = 0;
emit_subscript_location(mod, &code, (AstSubscript *) source_expr, &o2);
offset += o2;
} else if ((source_expr->kind == Ast_Kind_Local || source_expr->kind == Ast_Kind_Param)
- && source_expr->type->kind != Type_Kind_Pointer) {
+ && source_expr->type->kind != Type_Kind_Pointer && source_expr->type->kind != Type_Kind_MultiPointer) {
u64 o2 = 0;
emit_local_location(mod, &code, (AstLocal *) source_expr, &o2);
offset += o2;
} else if (source_expr->kind == Ast_Kind_Memres
- && source_expr->type->kind != Type_Kind_Pointer) {
+ && source_expr->type->kind != Type_Kind_Pointer && source_expr->type->kind != Type_Kind_MultiPointer) {
emit_memory_reservation_location(mod, &code, (AstMemRes *) source_expr);
} else {
if (t->kind == Type_Kind_Slice) return 's';
if (t->kind == Type_Kind_Pointer) return 'p';
+ if (t->kind == Type_Kind_MultiPointer) return 'p';
if (t->kind == Type_Kind_Enum) return encode_type_as_dyncall_symbol(t->Enum.backing);
if (t->kind == Type_Kind_Basic) {
TypeBasic* basic = &t->Basic;
break;
}
+ case Type_Kind_MultiPointer: {
+ table_info[type_idx] = table_buffer.length;
+ bh_buffer_write_u32(&table_buffer, type->kind);
+ bh_buffer_write_u32(&table_buffer, type_size_of(type));
+ bh_buffer_write_u32(&table_buffer, type_alignment_of(type));
+ bh_buffer_write_u32(&table_buffer, type->MultiPointer.elem->id);
+ break;
+ }
+
case Type_Kind_Array: {
table_info[type_idx] = table_buffer.length;
bh_buffer_write_u32(&table_buffer, type->kind);
from_stack :: macro (size: u32) -> rawptr {
// This should do something about the alignment...
// Everything so far has assume that the stack is aligned to 16 bytes.
- defer __stack_top = ~~(cast(&u8) __stack_top + size);
+ defer __stack_top = ~~(cast([&]u8) __stack_top + size);
return __stack_top;
}
array_from_stack :: macro ($T: type_expr, size: u32) -> [] T {
- defer __stack_top = ~~(cast(&u8) __stack_top + size * sizeof T);
- return (cast(&T) __stack_top)[0 .. size];
+ defer __stack_top = ~~(cast([&]u8) __stack_top + size * sizeof T);
+ return (cast([&]T) __stack_top)[0 .. size];
}
on_heap :: macro (v: $V) -> &V {
alloc_arena.current_arena = new_arena;
- return cast(rawptr) (cast(&u8) ret_arena + sizeof rawptr);
+ return cast(rawptr) (cast([&] u8) ret_arena + sizeof rawptr);
}
if alloc_arena.size % align != 0 {
alloc_arena.current_arena = new_arena;
}
- retval := cast(rawptr) (cast(&u8) alloc_arena.current_arena + alloc_arena.size);
+ retval := cast(rawptr) (cast([&] u8) alloc_arena.current_arena + alloc_arena.size);
alloc_arena.size += size;
return retval;
old: &GCLink;
if oldptr != null {
- old = (cast(&GCLink) oldptr) - 1;
+ old = (cast([&] GCLink) oldptr) - 1;
//
// If this allocated space was not from an gc allocator,
}
}
- return newptr + 1;
+ return cast([&] GCLink, newptr) + 1;
}
untrack :: (ptr: rawptr) -> bool {
- link := (cast(&GCLink) ptr) - 1;
+ link: &GCLink = (cast([&] GCLink) ptr) - 1;
if link.magic_number != GC_Link_Magic_Number {
return false;
// and then marked an "manually managed", we can free the block
// as normal here, but we have to go back some more bytes.
if hb_ptr.magic_number == core.alloc.gc.GC_Manually_Free_Magic_Number {
- hb_ptr = ~~(cast(uintptr) (cast(&core.alloc.gc.GCLink, ptr) - 1) - sizeof heap_allocated_block);
+ hb_ptr = ~~(cast(uintptr) (cast([&] core.alloc.gc.GCLink, ptr) - 1) - sizeof heap_allocated_block);
}
#if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex);
if aa == .Alloc {
retval := null;
if ss.curr + size < ss.size {
- retval = cast(&u8) ss.base_ptr + ss.curr;
+ retval = cast([&] u8) ss.base_ptr + ss.curr;
ss.curr += size;
}
elseif size <= ss.size {
// A string is simply a slice of bytes, and a c-string is a pointer
// to byte, with a null-terminator ('\0') at the end.
str :: #type [] u8;
-cstr :: #type & u8;
+cstr :: #type [&] u8;
dyn_str :: #type [..] u8;
for s_info.members {
if it.default != null {
member_size := type_info.size_of(it.type);
- memory.copy(cast(&u8) res + it.offset, it.default, member_size);
+ memory.copy(cast([&] u8) res + it.offset, it.default, member_size);
}
}
}
Bucket :: struct (T: type_expr) {
count : i32;
- data : &T; // Actually an array of elements_per_bucket things, but putting that
- // that into the type system makes these cumbersome to work with.
+ data : [&] T; // Actually an array of elements_per_bucket things, but putting that
+ // that into the type system makes these cumbersome to work with.
}
}
(ctx) => {
if ctx.i >= ctx.s.entries.count {
- return (typeof &ctx.s.entries.data.value).{}, false;
+ return (typeof &ctx.s.entries.data[0].value).{}, false;
}
defer ctx.i += 1;
n = -n;
}
- c := &buf[buf.count - 1];
+ c: [&] u8 = ~~&buf[buf.count - 1];
len := 0;
BASE64_MAP := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
while n > 0 {
m := cast(u64) n % base;
- *c = BASE64_MAP[cast(u32) m];
+ c[0] = BASE64_MAP[cast(u32) m];
len += 1;
c -= 1;
n /= base;
} else {
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
if min_length > 0 && len < min_length {
for i: min_length - len {
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
if prefix {
if base == 16 {
- *c = #char "x";
+ c[0] = #char "x";
len += 1;
c -= 1;
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
if base == 2 {
- *c = #char "b";
+ c[0] = #char "b";
len += 1;
c -= 1;
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
}
if is_neg {
- *c = #char "-";
+ c[0] = #char "-";
len += 1;
c -= 1;
}
// Converts an unsigned number into a string using the buffer provided.
// Behaves like i64_to_str.
u64_to_str :: (n: u64, base: u64, buf: [] u8, min_length := 0, prefix := false) -> str {
- c := &buf[buf.count - 1];
+ c: [&] u8 = ~~&buf[buf.count - 1];
len := 0;
BASE64_MAP := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
while n > 0 {
m := cast(u64) n % base;
- *c = BASE64_MAP[cast(u32) m];
+ c[0] = BASE64_MAP[cast(u32) m];
len += 1;
c -= 1;
n /= base;
} else {
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
if min_length > 0 && len < min_length {
for i: min_length - len {
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
if prefix {
if base == 16 {
- *c = #char "x";
+ c[0] = #char "x";
len += 1;
c -= 1;
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
if base == 2 {
- *c = #char "b";
+ c[0] = #char "b";
len += 1;
c -= 1;
- *c = #char "0";
+ c[0] = #char "0";
len += 1;
c -= 1;
}
// When the internal buffer is filled, `flush` is called to empty the
// buffer to the final destination.
Format_Output :: struct {
- data: &u8;
+ data: [&] u8;
count: u32;
capacity: u32;
format.quote_strings = true;
output->write("Some(");
- format_any(output, &format, .{ ~~(cast(&u8) v.data + s.members[1].offset), s.members[1].type });
+ format_any(output, &format, .{ ~~(cast([&] u8) v.data + s.members[1].offset), s.members[1].type });
output->write(")");
} else {
output->write(member.name);
output->write(" = ");
- format_any(output, &format, .{ ~~(cast(&u8) v.data + member.offset), member.type });
+ format_any(output, &format, .{ ~~(cast([&] u8) v.data + member.offset), member.type });
}
}
output->write("]");
}
- if info.kind == .Pointer {
+ if info.kind == .Pointer || info.kind == .Multi_Pointer {
value := *(cast(&rawptr) v.data);
ibuf : [128] u8;
for _: format.indentation do output->write(#char " ");
}
- format_any(output, &format, .{ ~~(cast(&u8) data + get_type_info(a.of).size * i), a.of });
+ format_any(output, &format, .{ ~~(cast([&] u8) data + get_type_info(a.of).size * i), a.of });
}
for i: a.count {
if i != 0 do output->write(", ");
- format_any(output, formatting, .{ ~~(cast(&u8) data + get_type_info(a.of).size * i), a.of });
+ format_any(output, formatting, .{ ~~(cast([&] u8) data + get_type_info(a.of).size * i), a.of });
}
output->write(" ]");
header := &any_headers[entry.index];
if header.offset == -1 do continue;
- target := cast(&u8) &out + header.offset;
+ target := cast([&] u8) &out + header.offset;
if header.type == str {
*cast(&str) target = string.alloc_copy(entry.value);
case .Array {
a_info := cast(&type_info.Type_Info_Array, info);
- base: &u8 = ~~v.data;
+ base: [&] u8 = ~~v.data;
elem_size := type_info.size_of(a_info.of);
for a_info.count {
s_info := cast(&type_info.Type_Info_Slice, info);
untyped_slice := cast(&array.Untyped_Array, v.data);
- base: &u8 = untyped_slice.data;
- count: = untyped_slice.count;
+ base: [&] u8 = untyped_slice.data;
+ count: = untyped_slice.count;
elem_size := type_info.size_of(s_info.of);
output_u32(w, count);
case .Struct {
s_info := cast(&type_info.Type_Info_Struct, info);
- base: &u8 = ~~v.data;
+ base: [&] u8 = ~~v.data;
for& member: s_info.members {
try(serialize(any.{ base + member.offset, member.type }, w));
case .Array {
a_info := cast(&type_info.Type_Info_Array, info);
- base: &u8 = target;
+ base: [&] u8 = target;
elem_size := type_info.size_of(a_info.of);
for a_info.count {
untyped_slice.allocator = context.allocator;
}
- base: &u8 = untyped_slice.data;
+ base: [&] u8 = untyped_slice.data;
for count {
try(deserialize(base + it * elem_size, s_info.of, r));
case .Struct {
s_info := cast(&type_info.Type_Info_Struct, info);
- base: &u8 = target;
+ base: [&] u8 = target;
for& member: s_info.members {
try(deserialize(base + member.offset, member.type, r));
__byte_dump :: (ptr: rawptr, byte_count: u32, bytes_per_line := 8) {
temp: [3] u8;
- u8_ptr := cast(&u8) ptr;
+ u8_ptr := cast([&] u8) ptr;
for i: byte_count {
val := u8_ptr[i];
}
return any.{
- cast(&u8) base_ptr + get_type_info(elem_type).size * index,
+ cast([&] u8) base_ptr + get_type_info(elem_type).size * index,
elem_type
};
}
if t.kind == .Struct {
member := get_struct_member(v.type, member_name);
if member != null {
- return any.{cast(&u8) v.data + member.offset, member.type};
+ return any.{cast([&] u8) v.data + member.offset, member.type};
}
}
member := get_struct_member(v.type, part_name);
if member {
if next_name {
- return any_nested_selector(any.{cast(&u8) v.data + member.offset, member.type}, next_name);
+ return any_nested_selector(any.{cast([&] u8) v.data + member.offset, member.type}, next_name);
}
return any.{
- cast(&u8, v.data) + member.offset, member.type
+ cast([&] u8, v.data) + member.offset, member.type
};
}
(ctx: $T) -> (any, bool) {
if ctx.index < ctx.count {
defer ctx.index += 1;
- return any.{ cast(&u8) ctx.base_ptr + ctx.elem_size * ctx.index, ctx.elem_type }, true;
+ return any.{ cast([&] u8) ctx.base_ptr + ctx.elem_size * ctx.index, ctx.elem_type }, true;
}
return .{}, false;
switch member.type {
case bool {
- *(cast(&bool) (cast(&u8) data_base + member.offset)) = !*(cast(&bool) (cast(&u8) data_base + member.offset));
+ *(cast(&bool) (cast([&] u8) data_base + member.offset)) = !*(cast(&bool) (cast([&] u8) data_base + member.offset));
}
case i32 {
if !success do return false;
value := conv.str_to_i64(value_str);
- *(cast(&i32) (cast(&u8) data_base + member.offset)) = ~~value;
+ *(cast(&i32) (cast([&] u8) data_base + member.offset)) = ~~value;
}
case str {
value, success := iter.take_one(arg_iter, no_close=true);
if !success do return false;
- *(cast(&str) (cast(&u8) data_base + member.offset)) = value;
+ *(cast(&str) (cast([&] u8) data_base + member.offset)) = value;
}
case #default {
// at the address where the addr field is in the Socket_Address.
// We also have to append a null-terminator, as that is what will
// be expected from any C function.
- out_path := cast(&u8) &out.addr;
+ out_path := cast([&] u8) &out.addr;
offset := 0;
while offset < math.min(path.count, UNIX_SOCKET_PATH_LEN - 1) {
defer offset += 1;
get_contents_from_file :: (file: &File) -> str {
size := cast(u32) io.stream_size(file);
- data := cast(&u8) raw_alloc(context.allocator, size);
+ data := cast([&] u8) raw_alloc(context.allocator, size);
_, prev_loc := io.stream_tell(file);
io.stream_seek(file, 0, .Start);
write_type_name(writer, pointer.to);
}
+ case .Multi_Pointer {
+ pointer := cast(&Type_Info_Multi_Pointer) info;
+ io.write_str(writer, "[&] ");
+ write_type_name(writer, pointer.to);
+ }
+
case .Array {
arr := cast(&Type_Info_Array) info;
io.write_format(writer, "[{}] ", arr.count);
Invalid :: 0x00; // Unused
Basic :: 0x01;
Pointer :: 0x02;
- Function :: 0x03;
- Struct :: 0x04;
- Polymorphic_Struct :: 0x05;
- Compound :: 0x06;
- Array :: 0x07;
- Slice :: 0x08;
- Dynamic_Array :: 0x09;
- Variadic_Argument :: 0x0a;
- Enum :: 0x0b;
- Distinct :: 0x0c;
+ Multi_Pointer :: 0x03;
+ Function :: 0x04;
+ Struct :: 0x05;
+ Polymorphic_Struct :: 0x06;
+ Compound :: 0x07;
+ Array :: 0x08;
+ Slice :: 0x09;
+ Dynamic_Array :: 0x0A;
+ Variadic_Argument :: 0x0B;
+ Enum :: 0x0C;
+ Distinct :: 0x0D;
}
kind := Kind.Invalid;
to: type_expr;
}
+Type_Info_Multi_Pointer :: struct {
+ use base : Type_Info;
+
+ // @Rename
+ to: type_expr;
+}
+
Type_Info_Function :: struct {
use base : Type_Info;
write_byte = (use fs: &os.File, byte: u8) -> io.Error {
b := byte;
bytes_wrote: u64;
- error := __file_write(data, .{ &b, 1 }, &bytes_wrote);
+ error := __file_write(data, .{ ~~&b, 1 }, &bytes_wrote);
return error;
},
use core {math}
String_Buffer :: struct {
- data : &u8;
+ data : [&] u8;
count : u32;
capacity : u32;
}
#match as_str from_cstr
from_cstr :: (s: cstr) -> str {
- return .{ data = s, count = length(s) };
+ return .{ data = ~~s, count = length(s) };
}
#overload
length :: (s: cstr) -> u32 {
len := 0;
- c := s;
- while *c != #char "\0" {
+ c: [&] u8 = s;
+ while c[0] != #char "\0" {
len += 1;
c += 1;
}
len1 := length(s1);
len2 := length(s2);
- data := cast(&u8) raw_alloc(allocator, len1 + len2);
+ data := cast([&] u8) raw_alloc(allocator, len1 + len2);
memory.copy(data, s1.data, len1);
memory.copy(data + len1, s2.data, len2);
total_length := 0;
for s: strings do total_length += s.count;
- data := cast(&u8) raw_alloc(allocator, total_length);
+ data := cast([&] u8) raw_alloc(allocator, total_length);
offset := 0;
for s: strings {
memory.copy(data + offset, s.data, s.count);
delim_count := 0;
for i: 0 .. s.count do if s[i] == delim do delim_count += 1;
- strarr := cast(&str) raw_alloc(allocator, sizeof str * (delim_count + 1));
+ strarr := cast([&] str) raw_alloc(allocator, sizeof str * (delim_count + 1));
curr_str := 0;
begin := 0;
offset: i64 = 0;
while !string.empty(file) {
- if *file.data == #char "x" {
+ if file.data[0] == #char "x" {
string.advance(&file, 2);
} else {
bus := conv.parse_int(&file);
total_scanning_error := 0;
-read_ticket_and_validate :: (file: &str, fields: [..] Field, ticket_store: &u32) -> bool {
+read_ticket_and_validate :: (file: &str, fields: [..] Field, ticket_store: [&] u32) -> bool {
retval := true;
for i: 0 .. fields.count {
while !string.empty(file) {
array.ensure_capacity(&ticket_data, ticket_data.count + fields.count);
- if read_ticket_and_validate(&file, fields, &ticket_data[ticket_data.count]) {
+ if read_ticket_and_validate(&file, fields, ~~ &ticket_data[ticket_data.count]) {
ticket_data.count += fields.count;
}
}
parse_factor :: (file: &str) -> u64 {
string.strip_leading_whitespace(file);
- switch *file.data {
+ switch file.data[0] {
case #char "0" .. #char "9" {
return conv.parse_int(file);
}
left := parse_factor(file);
string.strip_leading_whitespace(file);
- while *file.data == #char "+" {
+ while file.data[0] == #char "+" {
op := file.data[0];
string.advance(file, 1);
left := parse_expression_add(file);
string.strip_leading_whitespace(file);
- while *file.data == #char "*" {
+ while file.data[0] == #char "*" {
op := file.data[0];
string.advance(file, 1);
dim_2 := 1;
mem_size := sizeof bool * input.count * input.count * max_terminal;
- T := cast(&bool) calloc(mem_size);
+ T := cast([&] bool) calloc(mem_size);
defer cfree(T);
memory.set(T, ~~false, mem_size);
grammar_init(&grammar);
defer grammar_free(&grammar);
- while *file.data != #char "\n" {
+ while file[0] != #char "\n" {
nt0 := cast(u32, conv.parse_int(&file));
string.advance(&file, 2); // ': '
- if *file.data == #char "\"" {
+ if file[0] == #char "\"" {
string.advance(&file, 1); // '"'
t := file[0];
string.advance(&file, 1);
while true {
nt1 := cast(u32, conv.parse_int(&file));
- if *file.data == #char "\n" {
+ if file[0] == #char "\n" {
array.push(&grammar.unit_rules, Unit.{ nt0, nt1 });
break;
} else {
string.advance(&file, 1); // ' '
- if next_ch := *file.data; next_ch >= #char "0" && next_ch <= #char "9" {
+ if next_ch := file[0]; next_ch >= #char "0" && next_ch <= #char "9" {
nt2 := cast(u32, conv.parse_int(&file));
array.push(&grammar.production_rules, Prod.{ nt0, nt1, nt2 });
- if *file.data == #char " " do string.advance(&file, 1);
+ if file[0] == #char " " do string.advance(&file, 1);
} else {
array.push(&grammar.unit_rules, Unit.{ nt0, nt1 });
}
- if *file.data == #char "|" {
+ if file[0] == #char "|" {
string.advance(&file, 1); // ' |'
} else {
break;
t.orientation = ori;
}
-index_square_with_orientation :: (data: &$T, ori: TO, size: i32, x: i32, y: i32) -> &T {
+index_square_with_orientation :: (data: [&] $T, ori: TO, size: i32, x: i32, y: i32) -> &T {
switch ori {
case TO.N do return &data[x + y * size];
case TO.R90 do return &data[y + (size - 1 - x) * size];
#char" ",#char"#",#char" ",#char" ",#char"#",#char" ",#char" ",#char"#",#char" ",#char" ",#char"#",#char" ",#char" ",#char"#",#char" ",#char" ",#char"#",#char" ",#char" ",#char" ",
];
-scan_for_monsters :: (forest: &u8, ori: TO, width: u32, height: u32) -> bool {
+scan_for_monsters :: (forest: [&] u8, ori: TO, width: u32, height: u32) -> bool {
found_monsters := false;
for y: 0 .. height - sea_monster_height {
string.advance_line(&file);
- td := cast(&bool) raw_alloc(tile_allocator, sizeof TileData);
+ td := cast([&] bool) raw_alloc(tile_allocator, sizeof TileData);
for y: 0 .. 10 {
line, file~ := string.bisect(file, #char "\n");
for fy: 0 .. 8 {
for fx: 0 .. 8 {
- res := *index_square_with_orientation(cast(&bool) tile.data.data, tile.orientation, 10, fx + 1, fy + 1);
+ res := *index_square_with_orientation(cast([&] bool) tile.data.data, tile.orientation, 10, fx + 1, fy + 1);
loc := (y * 12 * 8 * 8) + (fy * 12 * 8) + (x * 8) + fx;
if res do forest[loc] = #char "#";
else do forest[loc] = #char ".";
}
for ori: .[ TO.N, TO.R90, TO.R180, TO.R270, TO.F, TO.FR90, TO.FR180, TO.FR270 ] {
- if scan_for_monsters(cast(&u8) forest, ori, 12 * 8, 12 * 8) do break;
+ if scan_for_monsters(cast([&] u8) forest, ori, 12 * 8, 12 * 8) do break;
}
safe_count := 0;
array.init(&food.ingredients, 16);
array.init(&food.allergens);
- while *file.data != #char "(" {
+ while file[0] != #char "(" {
ingredient_name := string.read_alphanum(&file);
string.advance(&file, 1); // ' '
string.advance(&file, 10); // '(contains '
- while *file.data != #char ")" {
+ while file[0] != #char ")" {
allergen_name := string.read_alphanum(&file);
- if *file.data == #char "," do string.advance(&file, 2); // ', '
+ if file[0] == #char "," do string.advance(&file, 2); // ', '
array.push(&food.allergens, allergen_name);
defer array.free(&player2);
string.advance_line(&file); // 'Player 1:'
- while *file.data != #char "\n" {
+ while file[0] != #char "\n" {
card := cast(u32, conv.parse_int(&file));
array.push(&player1, card);
rules: [..] Rule;
while !io.reader_empty(&reader) {
r: Rule;
- io.read_bytes(&reader, .{cast(&u8) &r.pair, 2});
+ io.read_bytes(&reader, .{cast([&] u8) &r.pair, 2});
io.skip_bytes(&reader, 4);
r.insert = io.read_byte(&reader);
}
alloc_slice :: ($T: type_expr, N: i32) -> [] T {
- data := cast(&T) calloc(sizeof T * N);
+ data := cast([&] T) calloc(sizeof T * N);
return .{ data, N };
}