From: Brendan Hansen Date: Tue, 21 Jul 2020 01:43:08 +0000 (-0500) Subject: Added array types; need to flush out semantics X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=b3ccec4dc91ebd50b6b3b826756f874c6b7ddeae;p=onyx.git Added array types; need to flush out semantics --- diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index cfa65923..2eb636fc 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -33,6 +33,7 @@ typedef struct AstType AstType; typedef struct AstBasicType AstBasicType; typedef struct AstPointerType AstPointerType; typedef struct AstFunctionType AstFunctionType; +typedef struct AstArrayType AstArrayType; typedef struct AstStructType AstStructType; typedef struct AstStructMember AstStructMember; @@ -74,6 +75,7 @@ typedef enum AstKind { Ast_Kind_Basic_Type, Ast_Kind_Pointer_Type, Ast_Kind_Function_Type, + Ast_Kind_Array_Type, Ast_Kind_Struct_Type, Ast_Kind_Type_End, @@ -263,6 +265,7 @@ struct AstType AstType_members; struct AstBasicType { AstType_base; Type* type; }; 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 AstStructType { AstType_base; diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 1f7ff864..2a941ab2 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -55,7 +55,8 @@ typedef struct StructMember { TYPE_KIND(Basic, TypeBasic) \ TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \ TYPE_KIND(Function, struct { Type *return_type; u64 param_count; Type* params[]; }) \ - TYPE_KIND(Struct, struct { char* name; u32 size; u32 mem_count; bh_table(StructMember) members; }) + TYPE_KIND(Struct, struct { char* name; u32 size; u32 mem_count; bh_table(StructMember) members; }) \ + TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; }) typedef enum TypeKind { Type_Kind_Invalid, diff --git a/onyx b/onyx index b260910c..f1f7782c 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/print_funcs.onyx b/progs/print_funcs.onyx index 2cd75ddc..fb7c0582 100644 --- a/progs/print_funcs.onyx +++ b/progs/print_funcs.onyx @@ -4,19 +4,19 @@ print_f32 :: proc #foreign "host" "print" (value: f32) --- print_i64 :: proc #foreign "host" "print" (value: i64) --- print_f64 :: proc #foreign "host" "print" (value: f64) --- -print_i32arr :: proc (arr: ^i32, len: i32) { +print_i32arr :: proc (arr: [] i32, len: i32) { for i: 0, len print(arr[i]); } -print_i64arr :: proc (arr: ^i64, len: i32) { +print_i64arr :: proc (arr: [] i64, len: i32) { for i: 0, len print(arr[i]); } -print_f32arr :: proc (arr: ^f32, len: i32) { +print_f32arr :: proc (arr: [] f32, len: i32) { for i: 0, len print(arr[i]); } -print_f64arr :: proc (arr: ^f64, len: i32) { +print_f64arr :: proc (arr: [] f64, len: i32) { for i: 0, len print(arr[i]); } @@ -29,7 +29,7 @@ print_str :: proc (str: ^u8) { } } -print_str_len :: proc (str: ^u8, len: i32) { +print_str_len :: proc (str: [] u8, len: i32) { for i: 0, len print(str[i] as i32); } diff --git a/progs/structs.onyx b/progs/structs.onyx index 1bf7f3e2..091e911d 100644 --- a/progs/structs.onyx +++ b/progs/structs.onyx @@ -1,6 +1,8 @@ use "progs/print_funcs" use "progs/intrinsics" +N :: 5 + Vec3 :: struct { x : f32; y : f32; @@ -31,7 +33,7 @@ foo_make :: proc -> ^Foo { return alloc(sizeof Foo) as ^Foo; } -foo_get :: proc (fooarr: ^Foo, i: i32) -> ^Foo { +foo_get :: proc (fooarr: []Foo, i: i32) -> ^Foo { return ^fooarr[i]; } @@ -46,7 +48,7 @@ proc #export "main" { foo1.v.y = 123.0f; print(foo1.v.y); - foo := alloc(sizeof Foo * 5) as ^Foo; + foo := alloc(sizeof [N]Foo) as [N]Foo; for i: 1, 6 { foo[i - 1].v.x = (i + 3) as f32; @@ -57,7 +59,7 @@ proc #export "main" { foo[i - 1].f = (i * 100) as f32; foo[i - 1].d = (i * 1000) as f64; - foo[i - 1].foo = foo; + foo[i - 1].foo = foo as ^Foo; } print(foo[3].v.x); // 7 @@ -76,6 +78,12 @@ proc #export "main" { print(1000000000000); link_test(); + + print(foo[3].v.x); // 7 + print(foo[4].i); // 5 + print(foo[2].d); // 3000.0 + print(foo[3].f); // 400.0 + print(foo[0].l); // 10 } Mut1 :: struct { @@ -129,4 +137,26 @@ link_test :: proc #export "main2" { link_create(4, node_head); link_print(*node_head); -} \ No newline at end of file +} + + + +// TODO: Make everything below this comment work +// SOA :: struct { +// x : [3]i32; +// y : [3]i32; +// } + +// soa_test :: proc #export "main" { +// m_arr := alloc(sizeof [5][5]i32) as [5][5]i32; + +// for y: 0, 5 { +// for x: 0, 5 { +// m_arr[y][x] = x + y * 5; +// } +// } + +// print(m_arr[2][4]); // 14 + +// print(sizeof SOA); +// } \ No newline at end of file diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 7fe714b4..35945643 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -435,7 +435,7 @@ CHECK(array_access, AstArrayAccess* aa) { if (!type_is_pointer(aa->addr->type)) { onyx_message_add(Msg_Type_Literal, aa->token->pos, - "expected pointer type for left of array access"); + "expected pointer or array type for left of array access"); return 1; } @@ -447,7 +447,17 @@ CHECK(array_access, AstArrayAccess* aa) { return 1; } - aa->type = aa->addr->type->Pointer.elem; + if (aa->addr->type->kind == Type_Kind_Pointer) + aa->type = aa->addr->type->Pointer.elem; + else if (aa->addr->type->kind == Type_Kind_Array) + aa->type = aa->addr->type->Array.elem; + else { + onyx_message_add(Msg_Type_Literal, + aa->token->pos, + "invalid type for left of array access"); + return 1; + } + aa->elem_size = type_size_of(aa->type); return 0; diff --git a/src/onyxlex.c b/src/onyxlex.c index ead0fa15..6db48c72 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -22,6 +22,7 @@ static const char* token_type_names[] = { "for", "break", "continue", + "sizeof", "->", "<-", @@ -121,7 +122,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { tk.type = Token_Type_Comment; tk.text = tokenizer->curr; - while (*tokenizer->curr != '\n') { + while (*tokenizer->curr != '\n' && tokenizer->curr != tokenizer->end) { INCREMENT_CURR_TOKEN(tokenizer); } diff --git a/src/onyxparser.c b/src/onyxparser.c index 9bc065b6..fc827d86 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -726,6 +726,18 @@ static AstType* parse_type(OnyxParser* parser) { next_insertion = &new->elem; } + else if (parser->curr->type == '[') { + AstArrayType* new = make_node(AstArrayType, Ast_Kind_Array_Type); + new->token = expect_token(parser, '['); + + if (parser->curr->type != ']') + new->count_expr = parse_expression(parser); + + expect_token(parser, ']'); + *next_insertion = (AstType *) new; + next_insertion = &new->elem; + } + else if (parser->curr->type == Token_Type_Symbol) { AstNode* symbol_node = make_node(AstNode, Ast_Kind_Symbol); symbol_node->token = expect_token(parser, Token_Type_Symbol); @@ -733,6 +745,12 @@ static AstType* parse_type(OnyxParser* parser) { next_insertion = NULL; } + else if (parser->curr->type == Token_Type_Keyword_Struct) { + AstStructType* s_node = parse_struct(parser); + *next_insertion = (AstType *) s_node; + next_insertion = NULL; + } + else { token_toggle_end(parser->curr); onyx_message_add(Msg_Type_Unexpected_Token, @@ -769,6 +787,8 @@ static AstStructType* parse_struct(OnyxParser* parser) { bh_arr_push(s_node->members, mem); } + expect_token(parser, '}'); + return s_node; } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 675cdef1..f2a59202 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -166,6 +166,15 @@ static AstType* symres_type(AstType* type) { return type; } + if (type->kind == Ast_Kind_Array_Type) { + AstArrayType* a_node = (AstArrayType *) type; + + if (a_node->count_expr) symres_expression(&a_node->count_expr); + a_node->elem = symres_type(a_node->elem); + + return type; + } + assert(("Bad type node", 0)); return NULL; } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 6b10c3c9..1f01b57d 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -48,7 +48,8 @@ b32 types_are_surface_compatible(Type* t1, Type* t2) { case Type_Kind_Struct: { if (t2->kind != Type_Kind_Struct) return 0; if (t1->Struct.mem_count != t2->Struct.mem_count) return 0; - if (strcmp(t1->Struct.name, t2->Struct.name) == 0) return 1; + if (t1->Struct.name && t2->Struct.name) + if (strcmp(t1->Struct.name, t2->Struct.name) == 0) return 1; b32 works = 1; bh_table_each_start(StructMember, t1->Struct.members); @@ -91,16 +92,27 @@ b32 types_are_compatible(Type* t1, Type* t2) { } break; - case Type_Kind_Pointer: + case Type_Kind_Pointer: { if (t2->kind == Type_Kind_Pointer) { return types_are_compatible(t1->Pointer.elem, t2->Pointer.elem); } break; + } + + case Type_Kind_Array: { + if (t2->kind != Type_Kind_Array) return 0; + + if (t1->Array.count != 0) + if (t1->Array.count != t2->Array.count) return 0; + + return types_are_compatible(t1->Array.elem, t2->Array.elem); + } case Type_Kind_Struct: { if (t2->kind != Type_Kind_Struct) return 0; if (t1->Struct.mem_count != t2->Struct.mem_count) return 0; - if (strcmp(t1->Struct.name, t2->Struct.name) == 0) return 1; + if (t1->Struct.name && t2->Struct.name) + if (strcmp(t1->Struct.name, t2->Struct.name) == 0) return 1; b32 works = 1; bh_table_each_start(StructMember, t1->Struct.members); @@ -132,6 +144,7 @@ u32 type_size_of(Type* type) { case Type_Kind_Basic: return type->Basic.size; case Type_Kind_Pointer: return 4; case Type_Kind_Function: return 0; + case Type_Kind_Array: return type->Array.size; case Type_Kind_Struct: return type->Struct.size; default: return 0; } @@ -163,6 +176,33 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return func_type; } + case Ast_Kind_Array_Type: { + AstArrayType* a_node = (AstArrayType *) type_node; + + Type* a_type = bh_alloc(alloc, sizeof(Type)); + a_type->kind = Type_Kind_Array; + a_type->Array.elem = type_build_from_ast(alloc, a_node->elem); + + u32 count = 0; + if (a_node->count_expr) { + a_node->count_expr->type = type_build_from_ast(alloc, a_node->count_expr->type_node); + + // NOTE: Currently, the count_expr has to be an I32 literal + if (a_node->count_expr->kind != Ast_Kind_NumLit + || a_node->count_expr->type->kind != Type_Kind_Basic + || a_node->count_expr->type->Basic.kind != Basic_Kind_I32) { + return NULL; + } + + count = ((AstNumLit *) a_node->count_expr)->value.i; + } + + a_type->Array.count = count; + a_type->Array.size = type_size_of(a_type->Array.elem) * count; + + return a_type; + } + case Ast_Kind_Struct_Type: { AstStructType* s_node = (AstStructType *) type_node; if (s_node->stcache != NULL) return s_node->stcache; @@ -230,7 +270,12 @@ 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_Struct: return type->Struct.name; + case Type_Kind_Array: return bh_aprintf(global_scratch_allocator, "[%d] %s", type->Array.count, type_get_name(type->Array.elem)); + case Type_Kind_Struct: + if (type->Struct.name) + return type->Struct.name; + else + return ""; default: return "unknown"; } } @@ -265,7 +310,8 @@ StructMember type_struct_lookup_member(Type* type, char* member) { } b32 type_is_pointer(Type* type) { - return type->kind == Type_Kind_Pointer || (type->Basic.flags & Basic_Flag_Pointer) != 0; + return (type->kind == Type_Kind_Pointer) + || (type->kind == Type_Kind_Array); } b32 type_is_struct(Type* type) { diff --git a/src/onyxutils.c b/src/onyxutils.c index 967556c8..0151a73e 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -30,6 +30,7 @@ static const char* ast_node_names[] = { "TYPE", "POINTER_TYPE", "FUNCTION_TYPE", + "ARRAY TYPE", "STRUCT TYPE", "TYPE_END (BAD)", diff --git a/src/onyxwasm.c b/src/onyxwasm.c index c5d9cc7e..93e21ead 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -205,6 +205,10 @@ static WasmType onyx_type_to_wasm_type(Type* type) { return WASM_TYPE_INT32; } + if (type->kind == Type_Kind_Array) { + return WASM_TYPE_INT32; + } + if (type->kind == Type_Kind_Basic) { TypeBasic* basic = &type->Basic; if (basic->flags & Basic_Flag_Boolean) return WASM_TYPE_INT32; @@ -240,7 +244,7 @@ COMPILE_FUNC(binop, AstBinaryOp* binop); COMPILE_FUNC(unaryop, AstUnaryOp* unop); COMPILE_FUNC(call, AstCall* call); COMPILE_FUNC(intrinsic_call, AstIntrinsicCall* call); -COMPILE_FUNC(array_access_location, AstArrayAccess* aa); +COMPILE_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return); COMPILE_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return); COMPILE_FUNC(expression, AstTyped* expr); COMPILE_FUNC(cast, AstUnaryOp* cast); @@ -348,13 +352,15 @@ COMPILE_FUNC(assignment, AstBinaryOp* assign) { } else if (lval->kind == Ast_Kind_Array_Access) { AstArrayAccess* aa = (AstArrayAccess *) lval; - compile_array_access_location(mod, &code, aa); + + u64 offset = 0; + compile_array_access_location(mod, &code, aa, &offset); compile_expression(mod, &code, assign->right); compile_store_instruction(mod, &code, aa->type, type_get_alignment_log2(aa->type), - 0); + offset); } else if (lval->kind == Ast_Kind_Field_Access) { AstFieldAccess* field = (AstFieldAccess *) lval; @@ -756,9 +762,11 @@ COMPILE_FUNC(intrinsic_call, AstIntrinsicCall* call) { *pcode = code; } -COMPILE_FUNC(array_access_location, AstArrayAccess* aa) { +COMPILE_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return) { bh_arr(WasmInstruction) code = *pcode; + *offset_return = 0; + compile_expression(mod, &code, aa->expr); if (aa->elem_size != 1) { WID(WI_I32_CONST, aa->elem_size); @@ -782,7 +790,9 @@ COMPILE_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return) { } if (source_expr->kind == Ast_Kind_Array_Access) { - compile_array_access_location(mod, &code, (AstArrayAccess *) source_expr); + u64 o2 = 0; + compile_array_access_location(mod, &code, (AstArrayAccess *) source_expr, &o2); + offset += o2; } else { compile_expression(mod, &code, source_expr); } @@ -856,7 +866,12 @@ COMPILE_FUNC(expression, AstTyped* expr) { case Ast_Kind_Array_Access: { AstArrayAccess* aa = (AstArrayAccess *) aof->expr; - compile_array_access_location(mod, &code, aa); + u64 offset = 0; + compile_array_access_location(mod, &code, aa, &offset); + if (offset != 0) { + WID(WI_I32_CONST, offset); + WI(WI_I32_ADD); + } break; } @@ -864,8 +879,10 @@ COMPILE_FUNC(expression, AstTyped* expr) { AstFieldAccess* field = (AstFieldAccess *) aof->expr; u64 offset = 0; compile_field_access_location(mod, &code, field, &offset); - WID(WI_I32_CONST, offset); - WI(WI_I32_ADD); + if (offset != 0) { + WID(WI_I32_CONST, offset); + WI(WI_I32_ADD); + } break; } @@ -887,8 +904,9 @@ COMPILE_FUNC(expression, AstTyped* expr) { case Ast_Kind_Array_Access: { AstArrayAccess* aa = (AstArrayAccess *) expr; - compile_array_access_location(mod, &code, aa); - compile_load_instruction(mod, &code, aa->type, 0); + u64 offset = 0; + compile_array_access_location(mod, &code, aa, &offset); + compile_load_instruction(mod, &code, aa->type, offset); break; } @@ -949,6 +967,11 @@ COMPILE_FUNC(cast, AstUnaryOp* cast) { return; } + if (to->kind == Type_Kind_Basic && to->Basic.kind == Basic_Kind_Void) { + WI(WI_DROP); + return; + } + i32 fromidx = -1, toidx = -1; if (from->Basic.flags & Basic_Flag_Pointer) { fromidx = 8;