added dynamic array type since polymorphism is now a thing
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 29 Aug 2020 01:57:57 +0000 (20:57 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 29 Aug 2020 01:57:57 +0000 (20:57 -0500)
14 files changed:
.vimspector.json
core/builtin.onyx
include/onyxastnodes.h
include/onyxtypes.h
onyx
progs/poly_test.onyx [new file with mode: 0644]
progs/wasi_test.onyx
src/onyxchecker.c
src/onyxclone.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxutils.c
src/onyxwasm.c

index 5388b49c347b5f46fb880185fc0b4eacd4e558ca..899b511c32ce13ca2eeb9c41aa3d9b9a230d0e77 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["-verbose", "progs/wasi_test.onyx"],
+                "args": ["-verbose", "progs/poly_test.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index 13df04fc13023c46f6e76bc149551b286a7b5593..e302b25244c0e396feab25023bb225b140ad0019 100644 (file)
@@ -38,6 +38,22 @@ calloc  :: proc (size: u32) -> rawptr do return alloc(context.allocator, size);
 cresize :: proc (ptr: rawptr, size: u32) -> rawptr do return resize(context.allocator, ptr, size);
 cfree   :: proc (ptr: rawptr) do free(context.allocator, ptr);
 
+array_init :: proc(arr: ^[..] $T) {
+    arr.count = 0;
+    arr.capacity = 4;
+    arr.data = calloc(sizeof T * arr.capacity);
+}
+
+array_add :: proc (arr: ^[..] $T, x: T) {
+    if arr.count + 1 > arr.capacity {
+        arr.capacity <<= 1;
+        arr.data = cresize(arr.data, sizeof T * arr.capacity);
+    }
+
+    arr.data[arr.count] = x;
+    arr.count += 1;
+}
+
 context : struct {
        allocator      : Allocator;
        temp_allocator : Allocator;
index 3caeed36673cfb4ef1b7b8c3204c15e202ebad0a..7d3106907e29ec6368baf1f326dc1acb88917afe 100644 (file)
@@ -41,6 +41,7 @@ typedef struct AstPointerType AstPointerType;
 typedef struct AstFunctionType AstFunctionType;
 typedef struct AstArrayType AstArrayType;
 typedef struct AstSliceType AstSliceType;
+typedef struct AstDynArrType AstDynArrType;
 typedef struct AstStructType AstStructType;
 typedef struct AstStructMember AstStructMember;
 typedef struct AstEnumType AstEnumType;
@@ -102,6 +103,7 @@ typedef enum AstKind {
     Ast_Kind_Function_Type,
     Ast_Kind_Array_Type,
     Ast_Kind_Slice_Type,
+    Ast_Kind_DynArr_Type,
     Ast_Kind_Struct_Type,
     Ast_Kind_Enum_Type,
     Ast_Kind_Type_Alias,
@@ -388,6 +390,7 @@ struct AstPointerType   { AstType_base; AstType* elem; };
 struct AstFunctionType  { AstType_base; AstType* return_type; u64 param_count; AstType* params[]; };
 struct AstArrayType     { AstType_base; AstType* elem; AstTyped *count_expr; };
 struct AstSliceType     { AstType_base; AstType* elem; };
+struct AstDynArrType    { AstType_base; AstType* elem; };
 struct AstStructType {
     AstType_base;
 
index dd4a209e0a0c290e7b4bd1c9f34fa52f7ed9943e..6eb3686b7ddbd31723f3eea8e17edd59a7b8e595 100644 (file)
@@ -69,6 +69,7 @@ typedef struct StructMember {
     })                                                            \
     TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; }) \
     TYPE_KIND(Slice, struct { Type *ptr_to_data; })               \
+    TYPE_KIND(DynArray, struct { Type *ptr_to_data; })            \
     TYPE_KIND(Enum, struct { char* name; Type* backing; }) 
 
 typedef enum TypeKind {
@@ -115,6 +116,7 @@ Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func);
 
 Type* type_make_pointer(bh_allocator alloc, Type* to);
 Type* type_make_slice(bh_allocator alloc, Type* of);
+Type* type_make_dynarray(bh_allocator alloc, Type* of);
 
 const char* type_get_name(Type* type);
 u32 type_get_alignment_log2(Type* type);
diff --git a/onyx b/onyx
index a68aa882e1dbab8a9cb98c3b0f70831dec24157b..7bf59014dd505ae7263ae8004e893d0b5d2a6c32 100755 (executable)
Binary files a/onyx and b/onyx differ
diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx
new file mode 100644 (file)
index 0000000..b1e367d
--- /dev/null
@@ -0,0 +1,58 @@
+package main
+
+#include_folder "/usr/share/onyx/core"
+
+#include_file "builtin"
+#include_file "wasi"
+#include_file "alloc"
+#include_file "intrinsics"
+#include_file "random"
+#include_file "string"
+#include_file "file"
+
+use package builtin
+
+// NOTE: Didn't realize this would work so easily
+use package core { string_builder_append as sba }
+use package core
+
+use package memory
+use package wasi
+use package intrinsics
+use package random
+use package file
+use package stdio
+
+print_arr_details :: proc (arr: ^[..] $T) {
+    print("\nArray details:\n");
+    print(arr.count);
+    print("\n");
+    print(arr.capacity);
+    print("\n");
+    print(cast(u32) arr.data, 16);
+    print("\n\n");
+}
+
+print_arr :: proc (arr: [..] $T) {
+    for i: 0, arr.count {
+        print(arr[i]);
+        print(" ");
+    }
+
+    print("\n");
+}
+
+main :: proc (args: [] cstring) {
+    arr : [..] i32;
+    array_init(^arr);
+
+    print_arr_details(^arr);
+
+    array_add(^arr, 1234);
+
+    for i: 0, 12 do array_add(^arr, i * 2 + 2);
+
+    print_arr_details(^arr);
+
+    print_arr(arr);
+}
\ No newline at end of file
index b225c14d238a1854ac61e7aa6347e18dd3293d56..62fbc25dec5e85da51d21a84d099f688886f7c19 100644 (file)
@@ -296,6 +296,20 @@ main :: proc (args: []cstring) {
 
     print(multi_poly(5.4f, 10l));
     print("\n");
+
+    dynarr : [..] Vec3;
+    array_init(^dynarr);
+    for i: 0, 16 do array_add(^dynarr, Vec3.{ cast(f32) i, cast(f32) (i * i), cast(f32) (i * i * i) });
+    for i: 0, 16 {
+        print(cast(u32) dynarr.data[i].x);
+        print(" ");
+        print(cast(u32) dynarr.data[i].y);
+        print(" ");
+        print(cast(u32) dynarr.data[i].z);
+        print("\n");
+    }
+
+    print(dynarr.count, 10);
 }
 
 foobar :: proc (a: i32, b := 1, c := 5l) {
index 8fbadea223a68e00aae1a0ac5e54de4db1bf8151..c3d1b54f83d36d9f4359df3ff64956d83337a169 100644 (file)
@@ -836,8 +836,9 @@ b32 check_array_access(AstArrayAccess* aa) {
         aa->type = aa->addr->type->Pointer.elem;
     else if (aa->addr->type->kind == Type_Kind_Array)
         aa->type = aa->addr->type->Array.elem;
-    else if (aa->addr->type->kind == Type_Kind_Slice) {
-        // If we are accessing on a slice, implicitly add a field access for the data member
+    else if (aa->addr->type->kind == Type_Kind_Slice
+            || aa->addr->type->kind == Type_Kind_DynArray) {
+        // If we are accessing on a slice or a dynamic array, implicitly add a field access for the data member
 
         StructMember smem;
         type_lookup_member(aa->addr->type, "data", &smem);
index f6c4b0f83c03cb50c43bd46aae48206eaeee7bbc..1c95c46e989ff16e9adcc73d7286f929b7eedda4 100644 (file)
@@ -18,7 +18,7 @@ static inline b32 should_clone(AstNode* node) {
                case Ast_Kind_Enum_Value:
                case Ast_Kind_Overloaded_Function:
                case Ast_Kind_Polymorphic_Proc:
-               return 0;
+                       return 0;
 
                default: return 1;
        }
@@ -52,9 +52,11 @@ static inline i32 ast_kind_to_size(AstKind kind) {
         case Ast_Kind_Function_Type: return sizeof(AstFunctionType);
         case Ast_Kind_Array_Type: return sizeof(AstArrayType);
         case Ast_Kind_Slice_Type: return sizeof(AstSliceType);
+        case Ast_Kind_DynArr_Type: return sizeof(AstDynArrType);
         case Ast_Kind_Struct_Type: return sizeof(AstStructType);
         case Ast_Kind_Enum_Type: return sizeof(AstEnumType);
         case Ast_Kind_Type_Alias: return sizeof(AstTypeAlias);
+        case Ast_Kind_Type_Raw_Alias: return sizeof(AstTypeRawAlias);
         case Ast_Kind_Type_End: return 0;
         case Ast_Kind_Struct_Member: return sizeof(AstStructMember);
         case Ast_Kind_Enum_Value: return sizeof(AstEnumValue);
@@ -128,6 +130,7 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                        ((AstUnaryOp *) nn)->type_node = (AstType *) ast_clone(a, ((AstUnaryOp *) node)->type_node);
                        break;
 
+               case Ast_Kind_Param:
                case Ast_Kind_Local:
                        ((AstLocal *) nn)->type_node = (AstType *) ast_clone(a, ((AstLocal *) node)->type_node);
                        break;
@@ -256,6 +259,10 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                        ((AstSliceType *) nn)->elem = (AstType *) ast_clone(a, ((AstSliceType *) node)->elem);
                        break;
 
+               case Ast_Kind_DynArr_Type:
+                       ((AstDynArrType *) nn)->elem = (AstType *) ast_clone(a, ((AstDynArrType *) node)->elem);
+                       break;
+
                case Ast_Kind_Type_Alias:
                        ((AstTypeAlias *) nn)->to = (AstType *) ast_clone(a, ((AstTypeAlias *) node)->to);
                        break;
index 587318b3abf7fd4bba4b670b4fa1c23168629682..85d51b0dec50e296495c7d7faf84b901804c7411 100644 (file)
@@ -1188,6 +1188,13 @@ static AstType* parse_type(OnyxParser* parser, bh_arr(AstPolyParam)* poly_vars)
             if (parser->curr->type == ']') {
                 new = make_node(AstSliceType, Ast_Kind_Slice_Type);
                 new->token = open_bracket;
+                
+            } else if (parser->curr->type == '.') {
+                new = make_node(AstDynArrType, Ast_Kind_DynArr_Type);
+                new->token = open_bracket;
+                consume_token(parser);
+                expect_token(parser, '.');
+
             } else {
                 new = make_node(AstArrayType, Ast_Kind_Array_Type);
                 new->token = open_bracket;
index aa891fad1edb54b09db9d764a507f1e825a7200b..7e4f10d52ee0b5d192c77eb9a46c8c4c0bb39e08 100644 (file)
@@ -123,6 +123,13 @@ static AstType* symres_type(AstType* type) {
         return type;
     }
 
+    if (type->kind == Ast_Kind_DynArr_Type) {
+        AstDynArrType* da_node = (AstDynArrType *) type;
+        da_node->elem = symres_type(da_node->elem);
+
+        return type;
+    }
+
     onyx_message_add(Msg_Type_Literal,
             (OnyxFilePos) { 0 },
             onyx_ast_node_kind_string(type->kind));
index 388c29575857411b19d24ff4c009f3077e5c2fe7..beade717c09c7a70341c8dc62a9180ebdace17d0 100644 (file)
@@ -94,6 +94,11 @@ b32 types_are_surface_compatible(Type* t1, Type* t2) {
             return types_are_compatible(t1->Slice.ptr_to_data->Pointer.elem, t2->Slice.ptr_to_data->Pointer.elem);
         }
 
+        case Type_Kind_DynArray: {
+            if (t2->kind != Type_Kind_DynArray) return 0;
+            return types_are_compatible(t1->DynArray.ptr_to_data->Pointer.elem, t2->DynArray.ptr_to_data->Pointer.elem);
+        }
+
         default:
             assert(("Invalid type", 0));
             break;
@@ -189,6 +194,11 @@ b32 types_are_compatible(Type* t1, Type* t2) {
             return types_are_compatible(t1->Slice.ptr_to_data->Pointer.elem, t2->Slice.ptr_to_data->Pointer.elem);
         }
 
+        case Type_Kind_DynArray: {
+            if (t2->kind != Type_Kind_DynArray) return 0;
+            return types_are_compatible(t1->DynArray.ptr_to_data->Pointer.elem, t2->DynArray.ptr_to_data->Pointer.elem);
+        }
+
         default:
             assert(("Invalid type", 0));
             break;
@@ -208,6 +218,7 @@ u32 type_size_of(Type* type) {
         case Type_Kind_Struct:   return type->Struct.size;
         case Type_Kind_Enum:     return type_size_of(type->Enum.backing);
         case Type_Kind_Slice:    return 8;
+        case Type_Kind_DynArray: return 12;
         default:                 return 0;
     }
 }
@@ -223,6 +234,7 @@ u32 type_alignment_of(Type* type) {
         case Type_Kind_Struct:   return type->Struct.alignment;
         case Type_Kind_Enum:     return type_alignment_of(type->Enum.backing);
         case Type_Kind_Slice:    return 4;
+        case Type_Kind_DynArray: return 4;
         default: return 1;
     }
 }
@@ -367,6 +379,10 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             return type_make_slice(alloc, type_build_from_ast(alloc, ((AstSliceType *) type_node)->elem));
         }
 
+        case Ast_Kind_DynArr_Type: {
+            return type_make_dynarray(alloc, type_build_from_ast(alloc, ((AstDynArrType *) type_node)->elem));
+        }
+
         case Ast_Kind_Basic_Type:
             return ((AstBasicType *) type_node)->type;
 
@@ -425,6 +441,14 @@ Type* type_make_slice(bh_allocator alloc, Type* of) {
     return slice_type;
 }
 
+Type* type_make_dynarray(bh_allocator alloc, Type* of) {
+    Type* dynarr = bh_alloc(alloc, sizeof(Type));
+    dynarr->kind = Type_Kind_DynArray;
+    dynarr->DynArray.ptr_to_data = type_make_pointer(alloc, of);
+
+    return dynarr;
+}
+
 const char* type_get_name(Type* type) {
     if (type == NULL) return "unknown";
 
@@ -445,6 +469,7 @@ const char* type_get_name(Type* type) {
 
         case Type_Kind_Function: return bh_aprintf(global_scratch_allocator, "proc (...) -> %s", type_get_name(type->Function.return_type));
         case Type_Kind_Slice: return bh_aprintf(global_scratch_allocator, "[] %s", type_get_name(type->Slice.ptr_to_data->Pointer.elem));
+        case Type_Kind_DynArray: return bh_aprintf(global_scratch_allocator, "[..] %s", type_get_name(type->DynArray.ptr_to_data->Pointer.elem));
 
         default: return "unknown";
     }
@@ -488,6 +513,27 @@ b32 type_lookup_member(Type* type, char* member, StructMember* smem) {
             return 0;
         }
 
+        case Type_Kind_DynArray: {
+            if (strcmp(member, "data") == 0) {
+                smem->idx = 0;
+                smem->offset = 0;
+                smem->type = type->DynArray.ptr_to_data;
+                return 1;
+            }
+            if (strcmp(member, "count") == 0) {
+                smem->idx = 1;
+                smem->offset = 4;
+                smem->type = &basic_types[Basic_Kind_U32];
+                return 1;
+            }
+            if (strcmp(member, "capacity") == 0) {
+                smem->idx = 2;
+                smem->offset = 8;
+                smem->type = &basic_types[Basic_Kind_U32];
+                return 1;
+            }
+        }
+
         default: return 0;
     }
 }
@@ -521,6 +567,27 @@ b32 type_lookup_member_by_idx(Type* type, i32 idx, StructMember* smem) {
             return 0;
         }
 
+        case Type_Kind_DynArray: {
+            if (idx == 0) {
+                smem->idx = 0;
+                smem->offset = 0;
+                smem->type = type->DynArray.ptr_to_data;
+                return 1;
+            }
+            if (idx == 1) {
+                smem->idx = 1;
+                smem->offset = 4;
+                smem->type = &basic_types[Basic_Kind_U32];
+                return 1;
+            }
+            if (idx == 2) {
+                smem->idx = 2;
+                smem->offset = 8;
+                smem->type = &basic_types[Basic_Kind_U32];
+                return 1;
+            }
+        }
+
         default: return 0;
     }
 }
@@ -600,37 +667,43 @@ b32 type_results_in_void(Type* type) {
 b32 type_is_array_accessible(Type* type) {
     if (type_is_pointer(type)) return 1;
     if (type->kind == Type_Kind_Slice) return 1;
+    if (type->kind == Type_Kind_DynArray) return 1;
     return 0;
 }
 
 b32 type_is_structlike(Type* type) {
     if (type->kind == Type_Kind_Struct) return 1;
     if (type->kind == Type_Kind_Slice)  return 1;
+    if (type->kind == Type_Kind_DynArray) return 1;
     if (type->kind == Type_Kind_Pointer) {
         if (type->Pointer.elem->kind == Type_Kind_Struct) return 1;
         if (type->Pointer.elem->kind == Type_Kind_Slice)  return 1;
+        if (type->Pointer.elem->kind == Type_Kind_DynArray) return 1;
     }
     return 0;
 }
 
 b32 type_is_structlike_strict(Type* type) {
-    if (type->kind == Type_Kind_Struct) return 1;
-    if (type->kind == Type_Kind_Slice)  return 1;
+    if (type->kind == Type_Kind_Struct)   return 1;
+    if (type->kind == Type_Kind_Slice)    return 1;
+    if (type->kind == Type_Kind_DynArray) return 1;
     return 0;
 }
 
 u32 type_structlike_mem_count(Type* type) {
     switch (type->kind) {
-        case Type_Kind_Struct: return type->Struct.mem_count;
-        case Type_Kind_Slice:  return 2;
+        case Type_Kind_Struct:   return type->Struct.mem_count;
+        case Type_Kind_Slice:    return 2;
+        case Type_Kind_DynArray: return 3;
         default: return 0;
     }
 }
 
 u32 type_structlike_is_simple(Type* type) {
     switch (type->kind) {
-        case Type_Kind_Struct: return type_struct_is_simple(type);
-        case Type_Kind_Slice:  return 1;
+        case Type_Kind_Struct:   return type_struct_is_simple(type);
+        case Type_Kind_Slice:    return 1;
+        case Type_Kind_DynArray: return 1;
         default: return 0;
     }
 }
\ No newline at end of file
index 94e5a520cfda93f35280906f11fb0bd4df134de4..e194fd8a7662af917ae8ccf7c8ebe893f03e59a9 100644 (file)
@@ -47,6 +47,7 @@ static const char* ast_node_names[] = {
     "FUNCTION_TYPE",
     "ARRAY TYPE",
     "SLICE TYPE",
+    "DYNARR TYPE",
     "STRUCT TYPE",
     "ENUM TYPE",
     "TYPE_ALIAS",
@@ -347,17 +348,29 @@ static Type* solve_poly_type(AstNode* target, AstType* type_expr, Type* actual)
 
         switch (type_expr->kind) {
             case Ast_Kind_Pointer_Type: {
+                if (actual->kind != Type_Kind_Pointer) return NULL;
+
                 type_expr = ((AstPointerType *) type_expr)->elem;
                 actual = actual->Pointer.elem;
                 break;
             }
 
             case Ast_Kind_Slice_Type: {
+                if (actual->kind != Type_Kind_Slice) return NULL;
+
                 type_expr = ((AstSliceType *) type_expr)->elem;
                 actual = actual->Slice.ptr_to_data->Pointer.elem;
                 break;
             }
 
+            case Ast_Kind_DynArr_Type: {
+                if (actual->kind != Type_Kind_DynArray) return NULL;
+
+                type_expr = ((AstDynArrType *) type_expr)->elem;
+                actual = actual->DynArray.ptr_to_data->Pointer.elem;
+                break;
+            }
+
             default:
                 return NULL;
         }
index e82a2015c93706dceffbd0ea9c3e73c9a3c5c2fd..13661c7a25049e1b1b8ad11baf88274d8c408ee1 100644 (file)
@@ -1714,6 +1714,15 @@ COMPILE_FUNC(cast, AstUnaryOp* cast) {
         return;
     }
 
+    if (from->kind == Type_Kind_DynArray || to->kind == Type_Kind_DynArray) {
+        onyx_message_add(Msg_Type_Literal,
+                cast->token->pos,
+                "cannot cast to or from a dynamic array");
+        WI(WI_DROP);
+        *pcode = code;
+        return;
+    }
+
     if (to->kind == Type_Kind_Function) {
         onyx_message_add(Msg_Type_Literal,
                 cast->token->pos,