From: Brendan Hansen Date: Sat, 29 Aug 2020 01:57:57 +0000 (-0500) Subject: added dynamic array type since polymorphism is now a thing X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=2701f24ebfdea09eedbf1fd6282d8cf1bcf4ef7e;p=onyx.git added dynamic array type since polymorphism is now a thing --- diff --git a/.vimspector.json b/.vimspector.json index 5388b49c..899b511c 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -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": [], diff --git a/core/builtin.onyx b/core/builtin.onyx index 13df04fc..e302b252 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -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; diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 3caeed36..7d310690 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -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; diff --git a/include/onyxtypes.h b/include/onyxtypes.h index dd4a209e..6eb3686b 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -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 a68aa882..7bf59014 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx new file mode 100644 index 00000000..b1e367d8 --- /dev/null +++ b/progs/poly_test.onyx @@ -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 diff --git a/progs/wasi_test.onyx b/progs/wasi_test.onyx index b225c14d..62fbc25d 100644 --- a/progs/wasi_test.onyx +++ b/progs/wasi_test.onyx @@ -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) { diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 8fbadea2..c3d1b54f 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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); diff --git a/src/onyxclone.c b/src/onyxclone.c index f6c4b0f8..1c95c46e 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -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; diff --git a/src/onyxparser.c b/src/onyxparser.c index 587318b3..85d51b0d 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index aa891fad..7e4f10d5 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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)); diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 388c2957..beade717 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -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 diff --git a/src/onyxutils.c b/src/onyxutils.c index 94e5a520..e194fd8a 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -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; } diff --git a/src/onyxwasm.c b/src/onyxwasm.c index e82a2015..13661c7a 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -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,