added: basics of multi-pointers
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 23 Mar 2023 14:20:17 +0000 (09:20 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 23 Mar 2023 14:20:17 +0000 (09:20 -0500)
need to work on ergonomics

42 files changed:
compiler/include/astnodes.h
compiler/include/types.h
compiler/src/astnodes.c
compiler/src/checker.c
compiler/src/clone.c
compiler/src/parser.c
compiler/src/polymorph.h
compiler/src/symres.c
compiler/src/types.c
compiler/src/wasm_emit.c
compiler/src/wasm_type_table.h
core/alloc/alloc.onyx
core/alloc/arena.onyx
core/alloc/gc.onyx
core/alloc/heap.onyx
core/alloc/ring.onyx
core/builtin.onyx
core/container/bucket_array.onyx
core/container/set.onyx
core/conv/conv.onyx
core/conv/format.onyx
core/encoding/csv.onyx
core/encoding/osad.onyx
core/io/stdio.onyx
core/misc/any_utils.onyx
core/misc/arg_parse.onyx
core/net/net.onyx
core/os/file.onyx
core/runtime/info/helper.onyx
core/runtime/info/types.onyx
core/runtime/platform/onyx/fs.onyx
core/string/buffer.onyx
core/string/string.onyx
tests/aoc-2020/day13.onyx
tests/aoc-2020/day16.onyx
tests/aoc-2020/day18.onyx
tests/aoc-2020/day19.onyx
tests/aoc-2020/day20.onyx
tests/aoc-2020/day21.onyx
tests/aoc-2020/day22.onyx
tests/aoc-2021/day14.onyx
tests/baked_parameters.onyx

index 1972298850ffa13511f9698fd5646d5b72be70cd..bb0422f2e9098b7d269551f49b63683dbacfce53 100644 (file)
@@ -60,6 +60,7 @@
     NODE(Type)                 \
     NODE(BasicType)            \
     NODE(PointerType)          \
+    NODE(MultiPointerType)     \
     NODE(FunctionType)         \
     NODE(ArrayType)            \
     NODE(SliceType)            \
@@ -158,6 +159,7 @@ typedef enum AstKind {
     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,
@@ -924,6 +926,7 @@ struct AstArrayType     { AstType_base; AstType* elem; AstTyped *count_expr; };
 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;
 
index dc8c979fd879f7077264c005c7186ba6d1e77d00..dfde30231ad334d695b81036a1313cd81f245d2f 100644 (file)
@@ -104,7 +104,14 @@ typedef enum StructProcessingStatus {
 
 #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;                                          \
@@ -207,6 +214,7 @@ Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func);
 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);
@@ -231,6 +239,7 @@ i32 type_get_idx_of_linear_member_with_offset(Type* type, u32 offset);
 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);
index f53943e856f67ee3c25a6a18e0011eddb1092835..98c520bcb906fb2f3a50db91242bcc952117ce60 100644 (file)
@@ -36,6 +36,7 @@ static const char* ast_node_names[] = {
     "TYPE",
     "BASIC_TYPE",
     "POINTER_TYPE",
+    "MULTI POINTER TYPE",
     "FUNCTION_TYPE",
     "ARRAY TYPE",
     "SLICE TYPE",
@@ -1355,7 +1356,8 @@ TypeMatch implicit_cast_to_bool(AstTyped **pnode) {
     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];
 
index a60be7c61b374090f36872710743c6fe29e6d1b4..fea13d0b4eaf37cb49797e95e5a8ec0b36474d14 100644 (file)
@@ -1071,10 +1071,11 @@ static b32 binary_op_is_allowed(BinaryOp operation, Type* type) {
 
     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;
@@ -1290,13 +1291,16 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
     }
 
     // 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;
 
@@ -1519,6 +1523,10 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) {
     }
     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;
 
index f5b31188bff850b537e349974acf930c50fc2b2e..f0c02fab6b7b9929211f4e5d5569212fe9e24dd9 100644 (file)
@@ -58,6 +58,7 @@ static inline i32 ast_kind_to_size(AstNode* node) {
         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);
@@ -330,6 +331,10 @@ AstNode* ast_clone(bh_allocator a, void* n) {
             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);
index 1a81139f91c77f1598c5b275318c5d384508bfb9..aa18ca87181829647b3809ad3797083347f382af 100644 (file)
@@ -1923,6 +1923,13 @@ static AstType* parse_type(OnyxParser* parser) {
                     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;
index b9b296a6d69df15dfd03a5a960730024a6a5a4d1..78e443f4db16f33c88dd9d2898dd4d7a39e4720b 100644 (file)
@@ -281,6 +281,17 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type
                 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;
 
index 0ce2c63facc51a6bc74fec58fbbeb6b47d601ed2..fb889375ead465d33f8dab5f283c4ef0d937d0c1 100644 (file)
@@ -182,6 +182,7 @@ static SymresStatus symres_type(AstType** type) {
         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;
index 0d632996f60a7b999b2eea407df34e7778078bff..7dd126a61e6befd6f91671aa590fab9fd737c032 100644 (file)
@@ -41,6 +41,7 @@ Type basic_types[] = {
 // 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;
@@ -65,12 +66,13 @@ static void type_register(Type* type) {
 }
 
 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]);
@@ -112,7 +114,7 @@ b32 types_are_compatible_(Type* t1, Type* t2, b32 recurse_pointers) {
                 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;
@@ -138,6 +140,21 @@ b32 types_are_compatible_(Type* t1, Type* t2, b32 recurse_pointers) {
             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;
 
@@ -223,6 +240,7 @@ u32 type_size_of(Type* type) {
 
     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;
@@ -242,6 +260,7 @@ u32 type_alignment_of(Type* type) {
 
     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);
@@ -267,6 +286,13 @@ static Type* type_build_from_ast_inner(bh_allocator alloc, AstType* type_node, b
             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;
@@ -832,6 +858,29 @@ Type* type_make_pointer(bh_allocator alloc, Type* to) {
     }
 }
 
+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;
@@ -871,7 +920,7 @@ Type* type_make_slice(bh_allocator alloc, Type* of) {
         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;
@@ -893,7 +942,7 @@ Type* type_make_dynarray(bh_allocator alloc, Type* of) {
         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;
@@ -915,7 +964,7 @@ Type* type_make_varargs(bh_allocator alloc, Type* of) {
         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;
@@ -1013,6 +1062,7 @@ const char* type_get_unique_name(Type* 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)
@@ -1079,6 +1129,7 @@ const char* type_get_name(Type* 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_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:
@@ -1153,11 +1204,12 @@ u32 type_get_alignment_log2(Type* type) {
 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;
     }
 }
@@ -1206,7 +1258,7 @@ b32 type_lookup_member(Type* type, char* member, StructMember* smem) {
             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;
                 }
@@ -1218,7 +1270,7 @@ b32 type_lookup_member(Type* type, char* member, StructMember* smem) {
             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;
@@ -1250,7 +1302,7 @@ b32 type_lookup_member_by_idx(Type* type, i32 idx, StructMember* smem) {
             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;
         }
@@ -1259,7 +1311,7 @@ b32 type_lookup_member_by_idx(Type* type, i32 idx, StructMember* smem) {
             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;
@@ -1284,7 +1336,7 @@ b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two) {
         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) {
@@ -1296,7 +1348,7 @@ b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two) {
         }
         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) {
@@ -1367,6 +1419,11 @@ b32 type_is_pointer(Type* type) {
     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;
@@ -1438,7 +1495,8 @@ b32 type_results_in_void(Type* type) {
 
 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;
index 8aaac08b934611c752e2195bdb9cdb12647cd62e..4841b8a28ea80c20ae8cfd0e681605375f8ab9fc 100644 (file)
@@ -48,6 +48,7 @@ static WasmType onyx_type_to_wasm_type(Type* type) {
     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;
@@ -91,6 +92,7 @@ static b32 local_is_wasm_local(AstTyped* local) {
     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;
 }
 
@@ -972,7 +974,7 @@ EMIT_FUNC(store_instruction, Type* type, u32 offset) {
     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 }));
@@ -1082,7 +1084,7 @@ EMIT_FUNC(load_instruction, Type* type, u32 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);
@@ -2699,19 +2701,19 @@ EMIT_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return) {
     }
 
     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 {
@@ -4127,6 +4129,7 @@ static char encode_type_as_dyncall_symbol(Type *t) {
 
     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;
index d80f2f0ed3c310800da12a2ce39d292edfa9ff05..fc620bce43ef2c4a48028f3b17843bc51c9c2e0d 100644 (file)
@@ -69,6 +69,15 @@ static u64 build_type_table(OnyxWasmModule* module) {
                 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);
index 25834be6d4ef37553bc95b15c2684f43f27e94d2..b9733c0f0a5d80399c5a95028c6f773999e90113 100644 (file)
@@ -16,13 +16,13 @@ as_allocator :: #match {
 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 {
index 0fce91fc81ff175df6a1e0cf94ce4c558cda8990..0f5c74f1e958c2799bb232300a1aa5a272bfbcf8 100644 (file)
@@ -49,7 +49,7 @@ arena_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32,
             
             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 {
@@ -67,7 +67,7 @@ arena_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32,
             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;
index 8ff2ebbfa7f44e8eb965b3fe7d749d81ff6f0869..3dc3e11d1f371e761f911b26ce566951f4ef17d3 100644 (file)
@@ -90,7 +90,7 @@ GC_Manually_Free_Magic_Number :: 0xface1337
     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,
@@ -136,11 +136,11 @@ GC_Manually_Free_Magic_Number :: 0xface1337
         }
     }
 
-    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;
index 79f90c8d5ac653e8b23e6e61cea91e4b16014d62..f5102f5f3f602950b6fb84f87202e8e9d1b797b0 100644 (file)
@@ -186,7 +186,7 @@ get_freed_size :: () => {
         // 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);
index a9c6891914e1f71e0188a7986f8f34b95838d73f..493a4572602cd25bf142c0cc91ca34b521bf1e59 100644 (file)
@@ -23,7 +23,7 @@ ring_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, o
     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 {
index 97544d49d858ea8e22d11203ecf37169e6e8d77d..f0ab09446c6f8ee915c164b5dcbe6e893662a401 100644 (file)
@@ -27,7 +27,7 @@ package builtin
 // 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;
 
 
@@ -292,7 +292,7 @@ cfree   :: (ptr: rawptr)            => raw_free(context.allocator, ptr);
             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);
                 }
             }
         }
index d54577bbd807c87081000178dca82d711e1eec21..098f0fcc31c9d7974b99259027e97083fa831b0e 100644 (file)
@@ -11,8 +11,8 @@ Bucket_Array :: struct (T: type_expr) {
 
     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.
     }
 }
 
index 29bc7aa2d22e68eeeaa4ea5bed0ac657b416c10c..6c7352e5000893e23a99d2dac2b3c5ef95dcc165 100644 (file)
@@ -133,7 +133,7 @@ as_iter :: (s: &Set) =>
 
         (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;
index 4bbd3b81fc1fdb7e4effb6ee5ddd87a33501ba79..e3dbdb6924dc6d1580034e0812891bb67387a915 100644 (file)
@@ -155,7 +155,7 @@ i64_to_str :: (n: i64, base: u64, buf: [] u8, min_length := 0, prefix := false)
         n = -n;
     }
 
-    c := &buf[buf.count - 1];
+    c: [&] u8 = ~~&buf[buf.count - 1];
     len := 0;
 
     BASE64_MAP := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
@@ -163,21 +163,21 @@ i64_to_str :: (n: i64, base: u64, buf: [] u8, min_length := 0, prefix := false)
     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;
         }
@@ -185,26 +185,26 @@ i64_to_str :: (n: i64, base: u64, buf: [] u8, min_length := 0, prefix := false)
 
     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;
     }
@@ -217,7 +217,7 @@ i64_to_str :: (n: i64, base: u64, buf: [] u8, min_length := 0, prefix := false)
 // 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+/";
@@ -225,21 +225,21 @@ u64_to_str :: (n: u64, base: u64, buf: [] u8, min_length := 0, prefix := false)
     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;
         }
@@ -247,19 +247,19 @@ u64_to_str :: (n: u64, base: u64, buf: [] u8, min_length := 0, prefix := false)
 
     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;
         }
index 1d89927bf1f888904eb2c656dc3b04a2b16e7bf6..2744345c23c3c28e7e66ca55375668125f03c468 100644 (file)
@@ -122,7 +122,7 @@ Custom_Parse_Proc :: struct {
 // 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;
 
@@ -551,7 +551,7 @@ format_any :: (output: &Format_Output, formatting: &Format, v: any) {
                         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 {
@@ -586,7 +586,7 @@ format_any :: (output: &Format_Output, formatting: &Format, v: any) {
                         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 });
                     }
                 }
                 
@@ -612,7 +612,7 @@ format_any :: (output: &Format_Output, formatting: &Format, v: any) {
                 output->write("]");
             }
 
-            if info.kind == .Pointer {
+            if info.kind == .Pointer || info.kind == .Multi_Pointer {
                 value := *(cast(&rawptr) v.data);
 
                 ibuf : [128] u8;
@@ -645,7 +645,7 @@ format_any :: (output: &Format_Output, formatting: &Format, v: any) {
                         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 });
                 }
 
 
@@ -669,7 +669,7 @@ format_any :: (output: &Format_Output, formatting: &Format, v: any) {
                 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(" ]");
index a223b6ec3328e56cfccb63b3570e4d0196a0dcfe..69ba266c3e43cdfe3fe8d387702f7e4baa234dc0 100644 (file)
@@ -111,7 +111,7 @@ CSV_Column :: struct {
                 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);
index 9ac3ba8d605a1115dce83bafc6432b5d2ef93875..66edc3b52e382e3fd0b5a6c0cf43203897636493 100644 (file)
@@ -60,7 +60,7 @@ serialize :: (v: any, w: &io.Writer) -> bool {
         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 {
@@ -72,8 +72,8 @@ serialize :: (v: any, w: &io.Writer) -> bool {
             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);
@@ -95,7 +95,7 @@ serialize :: (v: any, w: &io.Writer) -> bool {
         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));
@@ -166,7 +166,7 @@ deserialize :: (target: rawptr, type: type_expr, r: &io.Reader) -> bool {
         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 {
@@ -190,7 +190,7 @@ deserialize :: (target: rawptr, type: type_expr, r: &io.Reader) -> bool {
                 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));
@@ -200,7 +200,7 @@ deserialize :: (target: rawptr, type: type_expr, r: &io.Reader) -> bool {
         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));
index 23cc4b27ab8dea090610102b9ad307ecb07ff873..6a848979f2d4fbea60f512cf50b4be188ed6ab42 100644 (file)
@@ -133,7 +133,7 @@ tprintf :: (format: str, va: ..any) -> str {
 __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];
 
index c478a035fe04dab650c6b441f8b8cb9083d3da14..31d0235182563d000bb716207d74bbd0994c78cb 100644 (file)
@@ -45,7 +45,7 @@ any_subscript :: (v: any, index: i32) -> any {
     }
 
     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
     };
 }
@@ -57,7 +57,7 @@ any_selector :: (v: any, member_name: str) -> any {
     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};
         }
     }
 
@@ -75,11 +75,11 @@ any_nested_selector :: (v: any, member_name: str) -> any {
     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
         };
     }
 
@@ -139,7 +139,7 @@ any_iter :: (arr: any) -> Iterator(any) {
         (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;
index e3bde37010541155037374e7a16d3c603c805c97..5e3248810d7f1d9e53e41ecb6ba29143f952cc43 100644 (file)
@@ -49,7 +49,7 @@ arg_parse :: (c_args: [] cstr, output: any) -> bool {
 
                 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 {
@@ -57,14 +57,14 @@ arg_parse :: (c_args: [] cstr, output: any) -> bool {
                         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 {
index 59886132c9cdb2ba5715ce5a461662960311d5ce..810a7cf275247008893ad796dd12dd320e97a3d2 100644 (file)
@@ -91,7 +91,7 @@ make_unix_address :: (out: &Socket_Address, path: str) {
     // 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;
index 70a77314c0c02e07e7c1926ee87a5d7bf8292983..9a2e7b32fc7145385b96d7e67e00024bce1cb48a 100644 (file)
@@ -57,7 +57,7 @@ rename_file :: fs.__file_rename
 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);
index ce96d012778974ec978b071749800ed138a5b336..e063f1a01b630686f56121e55c69fb45d2a3d4d7 100644 (file)
@@ -47,6 +47,12 @@ write_type_name :: (writer: &io.Writer, t: type_expr) {
             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);
index 638da96b51b166484f87f3d295f1dead235966f9..2ed01221e22c9f941f2b4c56cad752017ae9dc30 100644 (file)
@@ -11,16 +11,17 @@ Type_Info :: struct {
         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;
@@ -75,6 +76,13 @@ Type_Info_Pointer :: struct {
     to: type_expr;
 }
 
+Type_Info_Multi_Pointer :: struct {
+    use base : Type_Info;
+
+    // @Rename
+    to: type_expr;
+}
+
 Type_Info_Function :: struct {
     use base : Type_Info;
 
index 3b49f1bfa6ed8238bccd5c8ca7519b2cc3f2f217..8ef4f1b973a027919bb0101c7af3105128820337 100644 (file)
@@ -97,7 +97,7 @@ __file_stream_vtable := io.Stream_Vtable.{
     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;
     },
 
index cbdd5533334b57bd3764afe6ea0a26003e5a7c25..ea9128208b73504f7d6d06728353e4c8e68d9918 100644 (file)
@@ -9,7 +9,7 @@ package core.string
 use core {math}
 
 String_Buffer :: struct {
-    data     : &u8;
+    data     : [&] u8;
     count    : u32;
     capacity : u32;
 }
index f16ae9b1191ca2c96620461217baabaa1936a363..e03097259de9dffe5145c59c27adce7744788228 100644 (file)
@@ -48,7 +48,7 @@ copy :: (orig: str, dest: str) {
 
 #match as_str from_cstr
 from_cstr :: (s: cstr) -> str {
-    return .{ data = s, count = length(s) };
+    return .{ data = ~~s, count = length(s) };
 }
 
 
@@ -60,8 +60,8 @@ length :: (s: str) => s.count;
 #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;
     }
@@ -77,7 +77,7 @@ concat :: (s1: str, s2: str, allocator := context.allocator) -> str {
     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);
 
@@ -94,7 +94,7 @@ concat :: (allocator: Allocator, strings: ..str) -> str {
     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);
@@ -564,7 +564,7 @@ split :: (s: str, delim: u8, allocator := context.allocator) -> []str {
     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;
index 65fe309a7d61f7db2027036166f7dfa947091ae8..ece1646c91a88748afa8d7dcec1698494fdfddba 100644 (file)
@@ -51,7 +51,7 @@ main :: (args: [] cstr) {
 
     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);
index 35331144158d14c7561adea3dc6d10cfe9d313b6..d1c2911788b2362aa9f7f39f9d35233322777a8c 100644 (file)
@@ -19,7 +19,7 @@ field_valid :: (use field: &Field, n: u32) -> bool {
 
 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 {
@@ -86,7 +86,7 @@ main :: (args: [] cstr) {
 
        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;
                }
        }
index ac8c69ce494b6007d7b8dda48c48cc3d45834c88..f690de0d45e550f9ed3544d8ff416c048921c3b5 100644 (file)
@@ -5,7 +5,7 @@ use package core
 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);
                }
@@ -31,7 +31,7 @@ parse_expression_add :: (file: &str) -> u64 {
        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);
 
@@ -51,7 +51,7 @@ parse_expression_mul :: (file: &str) -> u64 {
        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);
 
index 955f5602d74369dabcfbd8d83539f29ddd3f2410..da06eabb4e4505d085d501eba2567a56fe17b285 100644 (file)
@@ -76,7 +76,7 @@ cyk_algorithm :: (use grammar: &Grammar, input: str) -> bool {
     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);
 
@@ -113,12 +113,12 @@ main :: (args: [] cstr) {
     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);
@@ -129,23 +129,23 @@ main :: (args: [] cstr) {
             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;
index 7ddf6a8a52e5cba099a5632b508ae80cae8d62d2..c116d7130a1f538ce9b4a93bc90a3e03d6f8e459 100644 (file)
@@ -179,7 +179,7 @@ apply_orientation :: (t: &Tile, ori: TO) {
     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];
@@ -202,7 +202,7 @@ sea_monster := u8.[
     #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 {
@@ -264,7 +264,7 @@ main :: (args: [] cstr) {
 
                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");
@@ -352,7 +352,7 @@ main :: (args: [] cstr) {
 
             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 ".";
@@ -362,7 +362,7 @@ main :: (args: [] cstr) {
     }
 
     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;
index 33abd5f9a0008866dbeecd9a9bc6ab92308acdfe..01fdfedf7ed8c84b2ac41dc9b81005204ee27fc6 100644 (file)
@@ -51,7 +51,7 @@ main :: (args: [] cstr) {
         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); // ' '
 
@@ -70,9 +70,9 @@ main :: (args: [] cstr) {
 
         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);
 
index ab98c9de4f48395c00070752bcd3c5feff4344bb..fdbbf7b3480839c046320f8db9e76219f65a2d42 100644 (file)
@@ -110,7 +110,7 @@ main :: (args: [] cstr) {
     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);
 
index d43166f4dd9bf535d6b83ba20060e7618777d1c9..aa4e33613a2a1602233ff25a6a163f656e240563 100644 (file)
@@ -30,7 +30,7 @@ main :: (args) => {
         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);
 
index cb0e4cdd98b2565283fc3bb93e749d8498c3adca..eaf0d6034bcc8938d9a98e1f00a4ef38ceebdfb5 100644 (file)
@@ -8,7 +8,7 @@ count_to :: ($N: i32) {
 }
 
 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 };
 }