"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/onyx",
- "args": ["-verbose", "progs/wasi_test.onyx"],
+ "args": ["-verbose", "progs/poly_test.onyx"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
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;
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;
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,
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;
}) \
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 {
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);
--- /dev/null
+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
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) {
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);
case Ast_Kind_Enum_Value:
case Ast_Kind_Overloaded_Function:
case Ast_Kind_Polymorphic_Proc:
- return 0;
+ return 0;
default: return 1;
}
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);
((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;
((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;
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;
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));
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;
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;
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;
}
}
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;
}
}
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;
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";
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";
}
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;
}
}
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;
}
}
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
"FUNCTION_TYPE",
"ARRAY TYPE",
"SLICE TYPE",
+ "DYNARR TYPE",
"STRUCT TYPE",
"ENUM TYPE",
"TYPE_ALIAS",
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;
}
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,