Added array types; need to flush out semantics
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 21 Jul 2020 01:43:08 +0000 (20:43 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 21 Jul 2020 01:43:08 +0000 (20:43 -0500)
12 files changed:
include/onyxastnodes.h
include/onyxtypes.h
onyx
progs/print_funcs.onyx
progs/structs.onyx
src/onyxchecker.c
src/onyxlex.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxutils.c
src/onyxwasm.c

index cfa65923bb68cf5658d55918ebd9399a5fa4ba65..2eb636fca121c62f2cb276932e5e5e0976eee1db 100644 (file)
@@ -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;
 
index 1f7ff86471ec29f4435963985e44047ec716896f..2a941ab2d81ccf81bb5e79f3ed93861f025a8c38 100644 (file)
@@ -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 b260910cf00a23a6a8e48f85596b3ca9e4968dda..f1f7782c6458ef9397401bd2873a73ef8212f916 100755 (executable)
Binary files a/onyx and b/onyx differ
index 2cd75ddcad2598598c14c3236dae9d35a276ee62..fb7c058282bcde0285924c338e4f5a3997cba02c 100644 (file)
@@ -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);
 }
 
index 1bf7f3e24ddd7e82638ada2d3942e3f1fa34c82f..091e911d3d1267ac654462166ab0d6d5c3e43583 100644 (file)
@@ -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
index 7fe714b45cc7453161cc0cf5a360acbeeada4271..3594564341c8dd2a9d9ec92088680d9a9a9fa39f 100644 (file)
@@ -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;
index ead0fa15285f4684ac70a375b70b1e73175043ae..6db48c72549ac345fa1d8f04e8f05c03a9cd3bc9 100644 (file)
@@ -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);
         }
 
index 9bc065b6d50d1b768c5cb94f12331cf1cdc2e132..fc827d86a338a5cf0e1c3bf624d7937dcdb70829 100644 (file)
@@ -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;
 }
 
index 675cdef129f3f3669555e5b1d8341b5e95bc3891..f2a592029ccbf8c2c567cd77cbfdde804cc9840a 100644 (file)
@@ -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;
 }
index 6b10c3c9eae5ec8f8c77825c8eb93dca05a63318..1f01b57dcf7a6ce379111fa8ab6c45ac0e934fc3 100644 (file)
@@ -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 "<anonymous struct>";
         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) {
index 967556c86978838a4ddc42aeb29edf064d9602cf..0151a73eb9b23038a243c8fd04e9f040b245bdc8 100644 (file)
@@ -30,6 +30,7 @@ static const char* ast_node_names[] = {
     "TYPE",
     "POINTER_TYPE",
     "FUNCTION_TYPE",
+    "ARRAY TYPE",
     "STRUCT TYPE",
     "TYPE_END (BAD)",
 
index c5d9cc7e65c23ac7f04b80dcf5427b21b78db85e..93e21ead772065aeab79920960780786fbc43577 100644 (file)
@@ -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;