added basic struct literals; code cleanup
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 16 Aug 2020 20:28:42 +0000 (15:28 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 16 Aug 2020 20:28:42 +0000 (15:28 -0500)
12 files changed:
core/test.onyx [new file with mode: 0644]
docs/plan
include/bh.h
include/onyxastnodes.h
onyx
progs/stack_based.onyx
src/onyx.c
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxwasm.c

diff --git a/core/test.onyx b/core/test.onyx
new file mode 100644 (file)
index 0000000..07b11f2
--- /dev/null
@@ -0,0 +1,6 @@
+package core
+
+Buffer :: struct {
+       length: u32;
+       data: rawptr;
+}
\ No newline at end of file
index d35ece7a0afc14dfd2a8e95afa17a0cb08ec3296..c113975bf3a18ca716e885d5ecd60351dbc05ba9 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -172,15 +172,26 @@ HOW:
 
         [ ] Struct literals
 
+        [ ] #union on structs
+
+        [ ] #align on structs
+
         [ ] 'use' enums and packages at an arbitrary scope
 
+        [ ] Array literals
+
+        [ ] Top level variable initialization
+            - Works for numeric literals
+
         [ ] multiple lvals and compound assignment
             a := 2
             b := 5
             a, b = b, a;
-
+            
         [ ] All code paths return correct value
 
+        [ ] Type parameterized structs
+
         [ ] Add slices
             - Arrays without a size
             - Converted to a struct that looks like:    
@@ -205,13 +216,6 @@ HOW:
         [ ] returning structs
             - This will put forward a lot of the work that will be done for multiple return values
 
-        [ ] Type parameterized structs
-
-        [ ] Array literals
-
-        [ ] Top level variable initialization
-            - Works for numeric literals
-
         [X] Start work on evaluating compile time known values.
             - An expression marked COMPTIME will be reduced to its value in the parse tree.
 
index da64fb1e366b96e9afdfb2d6e4417c8052e8b5a4..6ae5e58b0855c286a0313a4492a29cb6bd020bb5 100644 (file)
@@ -166,7 +166,7 @@ u8* double_to_ieee754(f64 f, b32 reverse);
 #define BH_BIT(x)                        (1 << (x))
 #define BH_MASK_SET(var, set, mask)     ((set) ? (var) |= (mask) : (var) &= ~(mask))
 
-#define fori(var, lo, hi)                for (i64 var = (lo); var <= (hi); var++)
+#define fori(var, lo, hi)                for (i64 var = (lo); var < (hi); var++)
 #define forll(T, var, start, step)        for (T* var = (start); var != NULL; var = var->step)
 
 #ifdef BH_DEBUG
@@ -2142,7 +2142,7 @@ void bh_imap_init(bh_imap* imap, bh_allocator alloc, i32 hash_count) {
     bh_arr_new(alloc, imap->hashes, hash_count);
     bh_arr_new(alloc, imap->entries, 4);
 
-    fori(count, 0, hash_count - 1) bh_arr_push(imap->hashes, -1);
+    fori(count, 0, hash_count) bh_arr_push(imap->hashes, -1);
 }
 
 void bh_imap_free(bh_imap* imap) {
index fa2af347530359b33d4d4dc008f818708e48a21f..4334b4b433fd3b23cefb4ed5d909e7c7e2c8e575 100644 (file)
@@ -23,6 +23,7 @@ typedef struct AstFieldAccess AstFieldAccess;
 typedef struct AstSizeOf AstSizeOf;
 typedef struct AstAlignOf AstAlignOf;
 typedef struct AstFileContents AstFileContents;
+typedef struct AstStructLiteral AstStructLiteral;
 
 typedef struct AstReturn AstReturn;
 typedef struct AstBreak AstBreak;
@@ -40,7 +41,6 @@ typedef struct AstPointerType AstPointerType;
 typedef struct AstFunctionType AstFunctionType;
 typedef struct AstArrayType AstArrayType;
 typedef struct AstStructType AstStructType;
-typedef struct AstStructMember AstStructMember;
 typedef struct AstEnumType AstEnumType;
 typedef struct AstEnumValue AstEnumValue;
 typedef struct AstTypeAlias AstTypeAlias;
@@ -116,6 +116,7 @@ typedef enum AstKind {
     Ast_Kind_Size_Of,
     Ast_Kind_Align_Of,
     Ast_Kind_File_Contents,
+    Ast_Kind_Struct_Literal,
 
     Ast_Kind_If,
     Ast_Kind_For,
@@ -281,6 +282,7 @@ struct AstFieldAccess   { AstTyped_base; AstTyped *expr; u64 offset; };
 struct AstSizeOf        { AstTyped_base; AstType *so_type; u64 size; };
 struct AstAlignOf       { AstTyped_base; AstType *ao_type; u64 alignment; };
 struct AstFileContents  { AstTyped_base; OnyxToken *filename; };
+struct AstStructLiteral { AstTyped_base; AstTyped *stnode; bh_arr(AstTyped *) values; };
 
 // Intruction Node
 struct AstReturn        { AstNode_base; AstTyped* expr; };
@@ -328,14 +330,13 @@ struct AstArrayType     { AstType_base; AstType* elem; AstTyped *count_expr; };
 struct AstStructType {
     AstType_base;
 
-    bh_arr(AstStructMember *) members;
+    bh_arr(AstTyped *) members;
 
     // NOTE: Used to cache the actual type, since building
     // a struct type is kind of complicated and should
     // only happen once.
     Type *stcache;
 };
-struct AstStructMember { AstTyped_base; u64 offset; };
 struct AstEnumType {
     AstType_base;
     Scope *scope;
diff --git a/onyx b/onyx
index c33f8752c3d70f204e0a95ed506140066f8f75d1..dbe7cd69373f698c4e87bc9b6fa5bb84fb21731b 100755 (executable)
Binary files a/onyx and b/onyx differ
index b9d80080ddefa8ed487c23aabe2d8a648bba5652..c85c16105e9de45cca0ed3035dafd40d719b0172 100644 (file)
@@ -4,9 +4,11 @@ package main
 
 #include_file "printing"
 #include_file "alloc"
+#include_file "test"
 
 use package printing
 use package memory
+use package core as core
 
 sort :: proc (arr: [N]i32, cmp: proc (i32, i32) -> i32) -> [N] i32 {
     for i: 0, N {
@@ -50,8 +52,8 @@ Vec3 :: struct {
     z: i32;
 }
 
-mag_squared :: proc (v: Vec3) -> i32 {
-    return v.x * v.x + v.y * v.y + v.z * v.z;
+mag_squared :: proc (use v: Vec3) -> i32 {
+    return x * x + y * y + z * z;
 }
 
 vec_add :: proc (v: Vec3, u: Vec3, use out: ^Vec3) {
@@ -72,12 +74,12 @@ clamp :: proc (v: i32, lo: i32, hi: i32) -> i32 {
 //
 // This is intended behavior since creating new
 // procs at runtime is very difficult with WASM
-stupid_idea :: proc (n: i32) -> proc () -> i32 {
+stupid_idea :: proc (n: i32) -> proc (i32) -> i32 {
     if n == 1234 {
-        return proc -> i32 { return 5678; };
+        return proc (a: i32) -> i32 { return 5678 + a; };
     }
 
-    return proc -> i32 { return -1; };
+    return proc (a: i32) -> i32 { return -1 + a; };
 }
 
 some_value := 20 + 30 * 4 + 15 / 5;
@@ -129,36 +131,32 @@ start :: proc #export {
     for i: 0, N do something[i] = N - i;
     for i: 0, N do print(something[i]);
 
-    val := something
+    something
             |> sort(proc (a: i32, b: i32) -> i32 { return a - b; })
             |> sumN()
-            |> clamp(30, 100);
-    print(val);
+            |> clamp(30, 100)
+            |> print();
 
     for i: 0, N do
         something[i]
             |> clamp(3, 6)
             |> print();
 
-    stupid_idea(1234)() |> print();
+    stupid_idea(1234)(1234) |> print();
 
     varr : [5] Vec3;
-    varr[2].x = 4;
-    varr[2].y = 5;
-    varr[2].z = 6;
-    mag_squared(varr[2]) |> print();
+    varr[2] = Vec3 .{4, 5, 6};
 
-    v1 : Vec3;
-    v1.x = 1;
-    v1.y = 2;
-    v1.z = 4;
+    mag_squared(varr[2]) |> print();
 
-    v2 := v1;
+    v1 := Vec3 .{ 1, 2, 4 };
+    v2 := *vadd(Vec3.{4, 3, 2}, Vec3.{1, 1, 1});
+  
+    print(v2.x);
+    print(v2.y);
+    print(v2.z);
 
-    v3 := *vadd(v1, v2);
-    print(v3.x);
-    print(v3.y);
-    print(v3.z);
+    buf := core.Buffer.{ 16, null };
 }
 
 vadd :: proc (v1: Vec3, v2: Vec3) -> ^Vec3 {
index 51c9a03c979d9846c0ca376f1931702aff511b2c..9608963a406dce11fe59c451ab4e4971d0803f7f 100644 (file)
@@ -60,7 +60,7 @@ static OnyxCompileOptions compile_opts_parse(bh_allocator alloc, int argc, char
     // NOTE: Add the current folder
     bh_arr_push(options.included_folders, ".");
 
-    fori(i, 1, argc - 1) {
+    fori(i, 1, argc) {
         if (!strcmp(argv[i], "-help")) {
             options.action = ONYX_COMPILE_ACTION_PRINT_HELP;
             break;
@@ -160,10 +160,10 @@ static void compiler_state_free(CompilerState* cs) {
 
 static char* lookup_included_file(CompilerState* cs, OnyxToken* filename) {
     static char path[256];
-    fori (i, 0, 255) path[i] = 0;
+    fori (i, 0, 256) path[i] = 0;
 
     static char fn[128];
-    fori (i, 0, 127) fn[i] = 0;
+    fori (i, 0, 128) fn[i] = 0;
     token_toggle_end(filename);
     if (!bh_str_ends_with(filename->text, ".onyx")) {
         bh_snprintf(fn, 128, "%s.onyx", filename->text);
index 68f21b102f5780dfe402f61ffabe90c12ae75fdc..ed4e045e5ee98c2ff1a860542643b6ce4e0a8ca8 100644 (file)
@@ -15,6 +15,7 @@ CHECK(for, AstFor* fornode);
 CHECK(call, AstCall* call);
 CHECK(binaryop, AstBinaryOp** pbinop, b32 assignment_is_ok);
 CHECK(unaryop, AstUnaryOp** punop);
+CHECK(struct_literal, AstStructLiteral* sl);
 CHECK(expression, AstTyped** expr);
 CHECK(address_of, AstAddressOf* aof);
 CHECK(dereference, AstDereference* deref);
@@ -630,6 +631,37 @@ CHECK(unaryop, AstUnaryOp** punop) {
     return 0;
 }
 
+CHECK(struct_literal, AstStructLiteral* sl) {
+    fill_in_type((AstTyped *) sl);
+
+    TypeStruct* st = &sl->type->Struct;
+    if (st->mem_count != bh_arr_length(sl->values)) {
+        onyx_message_add(Msg_Type_Literal,
+                sl->token->pos,
+                "incorrect number of initial values for this type");
+        return 1;
+    }
+
+    AstTyped** actual = sl->values;
+    StructMember** formal = st->memarr;
+
+    fori (i, 0, st->mem_count) {
+        if (check_expression(actual)) return 1;
+
+        if (!types_are_compatible((*formal)->type, (*actual)->type)) {
+            onyx_message_add(Msg_Type_Assignment_Mismatch,
+                    (*actual)->token->pos,
+                    type_get_name((*formal)->type),
+                    type_get_name((*actual)->type));
+            return 1;
+        }
+
+        actual++, formal++;
+    }
+
+    return 0;
+}
+
 CHECK(address_of, AstAddressOf* aof) {
     if (check_expression(&aof->expr)) return 1;
 
@@ -813,6 +845,10 @@ CHECK(expression, AstTyped** pexpr) {
             assert(expr->type != NULL);
             break;
 
+        case Ast_Kind_Struct_Literal:
+            retval = check_struct_literal((AstStructLiteral *) expr);
+            break;
+
         case Ast_Kind_Function:
             expr->flags |= Ast_Flag_Function_Used;
             break;
@@ -951,7 +987,7 @@ CHECK(struct, AstStructType* s_node) {
         return 1;
     }
 
-    bh_arr_each(AstStructMember *, member, s_node->members) {
+    bh_arr_each(AstTyped *, member, s_node->members) {
         token_toggle_end((*member)->token);
 
         if (bh_table_has(i32, mem_set, (*member)->token->text)) {
index 3187a4921a5564f0396b47ded3f116e603e95441..39763fac8af1aed2a445ae446f16a42f3e127d07 100644 (file)
@@ -6,6 +6,14 @@
 // NOTE: The one weird define you need to know before read the code below
 #define make_node(nclass, kind) onyx_ast_node_new(parser->allocator, sizeof(nclass), kind)
 
+#define STORE_PARSER_STATE \
+    OnyxToken* __parser_curr = parser->curr; \
+    OnyxToken* __parser_prev = parser->prev;
+
+#define RESTORE_PARSER_STATE \
+    parser->curr = __parser_curr; \
+    parser->prev = __parser_prev;
+
 static AstNode error_node = { Ast_Kind_Error, 0, NULL, NULL };
 
 // NOTE: Forward declarations
@@ -16,12 +24,13 @@ static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type);
 
 static AstNumLit*     parse_int_literal(OnyxParser* parser);
 static AstNumLit*     parse_float_literal(OnyxParser* parser);
+static b32            parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret);
 static AstTyped*      parse_factor(OnyxParser* parser);
 static AstTyped*      parse_expression(OnyxParser* parser);
 static AstIf*         parse_if_stmt(OnyxParser* parser);
 static AstWhile*      parse_while_stmt(OnyxParser* parser);
 static AstFor*        parse_for_stmt(OnyxParser* parser);
-static b32            parse_symbol_declaration(OnyxParser* parser, AstNode** ret);
+static b32            parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret);
 static AstReturn*     parse_return_statement(OnyxParser* parser);
 static AstBlock*      parse_block(OnyxParser* parser);
 static AstNode*       parse_statement(OnyxParser* parser);
@@ -86,6 +95,19 @@ static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type) {
     return token;
 }
 
+static OnyxToken* soft_expect_token(OnyxParser* parser, TokenType token_type) {
+    if (parser->hit_unexpected_token) return NULL;
+
+    OnyxToken* token = parser->curr;
+
+    if (token->type == token_type) {
+        consume_token(parser);
+        return token;
+    }
+
+    return NULL;
+}
+
 static void add_node_to_process(OnyxParser* parser, AstNode* node) {
     bh_arr_push(parser->results.nodes_to_process, ((NodeToProcess) {
         .package = parser->package,
@@ -141,6 +163,70 @@ static AstNumLit* parse_float_literal(OnyxParser* parser) {
     return float_node;
 }
 
+static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret) {
+    if (parser->curr->type != Token_Type_Symbol) return 0;
+
+    STORE_PARSER_STATE;
+
+    OnyxToken *symbol1 = NULL, *symbol2 = NULL;
+    symbol1 = expect_token(parser, Token_Type_Symbol);
+
+    if (!soft_expect_token(parser, '.')) {
+        RESTORE_PARSER_STATE;
+        return 0;
+    }
+
+    if (parser->curr->type == Token_Type_Symbol) {
+        symbol2 = soft_expect_token(parser, Token_Type_Symbol);
+
+        if (!soft_expect_token(parser, '.')) {
+            RESTORE_PARSER_STATE;
+            return 0;
+        }
+    }
+
+    if (parser->curr->type != '{') {
+        RESTORE_PARSER_STATE;
+        return 0;
+    }
+
+    AstStructLiteral* sl = make_node(AstStructLiteral, Ast_Kind_Struct_Literal);
+    sl->token = parser->curr;
+    bh_arr_new(global_heap_allocator, sl->values, 4);
+
+    if (symbol2 != NULL) {
+        AstTyped *package = make_node(AstTyped, Ast_Kind_Symbol);
+        package->token = symbol1;
+
+        AstFieldAccess *fa = make_node(AstFieldAccess, Ast_Kind_Field_Access);
+        fa->token = symbol2;
+        fa->expr = package;
+
+        sl->stnode = (AstTyped *) fa;
+
+    } else {
+        sl->stnode = make_node(AstTyped, Ast_Kind_Symbol);
+        sl->stnode->token = symbol1;
+    }
+
+    expect_token(parser, '{');
+    while (parser->curr->type != '}') {
+        if (parser->hit_unexpected_token) break;
+
+        AstTyped *expr = parse_expression(parser);
+        bh_arr_push(sl->values, expr);
+
+        if (parser->curr->type != '}')
+            expect_token(parser, ',');
+    }
+
+    expect_token(parser, '}');
+
+    *ret = (AstTyped *) sl;
+
+    return 1;
+}
+
 // ( <expr> )
 // - <factor>
 // ! <factor>
@@ -235,6 +321,8 @@ static AstTyped* parse_factor(OnyxParser* parser) {
         }
 
         case Token_Type_Symbol: {
+            if (parse_possible_struct_literal(parser, &retval)) return retval;
+
             OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol);
             AstTyped* sym_node = make_node(AstTyped, Ast_Kind_Symbol);
             sym_node->token = sym_token;
@@ -678,7 +766,7 @@ static AstFor* parse_for_stmt(OnyxParser* parser) {
 // <symbol> : <type> : <expr>
 // <symbol> := <expr>
 // <symbol> :: <expr>
-static b32 parse_symbol_declaration(OnyxParser* parser, AstNode** ret) {
+static b32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret) {
     if (parser->curr->type != Token_Type_Symbol) return 0;
     if ((parser->curr + 1)->type != ':')         return 0;
 
@@ -772,7 +860,7 @@ static AstNode* parse_statement(OnyxParser* parser) {
             break;
 
         case Token_Type_Symbol:
-            if (parse_symbol_declaration(parser, &retval)) break;
+            if (parse_possible_symbol_declaration(parser, &retval)) break;
             // fallthrough
 
         case '(':
@@ -969,7 +1057,7 @@ static AstType* parse_type(OnyxParser* parser) {
             new->return_type = return_type;
 
             if (param_count > 0)
-                fori (i, 0, param_count - 1) new->params[i] = params[i];
+                fori (i, 0, param_count) new->params[i] = params[i];
 
             *next_insertion = (AstType *) new;
             next_insertion = NULL;
@@ -1026,8 +1114,7 @@ static AstStructType* parse_struct(OnyxParser* parser) {
     while (parser->curr->type != '}') {
         if (parser->hit_unexpected_token) return s_node;
 
-        AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member);
-        mem->offset = 0;
+        AstTyped* mem = make_node(AstTyped, Ast_Kind_Struct_Member);
 
         mem->token = expect_token(parser, Token_Type_Symbol);
         expect_token(parser, ':');
index 34573b4c47748e01d46dbffeaed6b24bc5ada141..40ad2738ae9621e650d779487f5b655c42226c72 100644 (file)
@@ -78,7 +78,7 @@ static AstType* symres_type(AstType* type) {
         ftype->return_type = symres_type(ftype->return_type);
 
         if (ftype->param_count > 0)
-            fori (i, 0, ftype->param_count - 1) {
+            fori (i, 0, ftype->param_count) {
                 ftype->params[i] = symres_type(ftype->params[i]);
             }
 
@@ -91,7 +91,7 @@ static AstType* symres_type(AstType* type) {
 
         s_node->flags |= Ast_Flag_Type_Is_Resolved;
 
-        bh_arr_each(AstStructMember *, member, s_node->members) {
+        bh_arr_each(AstTyped *, member, s_node->members) {
             (*member)->type_node = symres_type((*member)->type_node);
         }
 
@@ -203,6 +203,22 @@ static void symres_unaryop(AstUnaryOp** unaryop) {
         (*unaryop)->type_node = ((AstUnaryOp *)(*unaryop))->expr->type_node;
 }
 
+static void symres_struct_literal(AstStructLiteral* sl) {
+    if (sl->stnode != NULL) symres_expression(&sl->stnode);
+    if (sl->stnode == NULL) return;
+
+    if (sl->stnode->kind != Ast_Kind_Struct_Type) {
+        onyx_message_add(Msg_Type_Literal,
+                sl->token->pos,
+                "type is not a struct type (BAD ERROR MESSAGE)");
+        return;
+    }
+
+    sl->type_node = (AstType *) sl->stnode;
+
+    bh_arr_each(AstTyped *, expr, sl->values) symres_expression(expr);
+}
+
 static void symres_expression(AstTyped** expr) {
     switch ((*expr)->kind) {
         case Ast_Kind_Symbol:
@@ -213,7 +229,8 @@ static void symres_expression(AstTyped** expr) {
             symres_expression(&((AstBinaryOp *)(*expr))->left);
             symres_expression(&((AstBinaryOp *)(*expr))->right);
 
-            (*expr)->type_node = ((AstBinaryOp *)(*expr))->left->type_node;
+            if (((AstBinaryOp *) (*expr))->left)
+                (*expr)->type_node = ((AstBinaryOp *)(*expr))->left->type_node;
             break;
 
         case Ast_Kind_Unary_Op:     symres_unaryop((AstUnaryOp **) expr); break;
@@ -237,6 +254,10 @@ static void symres_expression(AstTyped** expr) {
             symres_expression(&((AstArrayAccess *)(*expr))->expr);
             break;
 
+        case Ast_Kind_Struct_Literal:
+            symres_struct_literal((AstStructLiteral *)(*expr));
+            break;
+
         default: break;
     }
 }
@@ -335,6 +356,8 @@ static void symres_function(AstFunction* func) {
         param->type_node = symres_type(param->type_node);
         param->type = type_build_from_ast(semstate.allocator, param->type_node);
 
+        if (param->type == NULL) break;
+
         symbol_introduce(semstate.curr_scope, param->token, (AstNode *) param);
 
         if (param->flags & Ast_Flag_Param_Use) {
@@ -346,7 +369,7 @@ static void symres_function(AstFunction* func) {
                     st = (AstStructType *) ((AstPointerType *) param->type_node)->elem;
                 }
 
-                bh_arr_each(AstStructMember *, mem, st->members) {
+                bh_arr_each(AstTyped *, mem, st->members) {
                     AstFieldAccess* fa = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
                     fa->token = (*mem)->token;
                     fa->type_node = (*mem)->type_node;
index 34f6c5ee95e9d18d1d96c3352452f5d1c2771e67..f683b292dff0b05bc42e40aa5a671eed8335fd83 100644 (file)
@@ -138,8 +138,6 @@ b32 types_are_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 (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);
@@ -169,7 +167,7 @@ b32 types_are_compatible(Type* t1, Type* t2) {
             if (!types_are_compatible(t1->Function.return_type, t2->Function.return_type)) return 0;
 
             if (t1->Function.param_count > 0) {
-                fori (i, 0, t1->Function.param_count - 1) {
+                fori (i, 0, t1->Function.param_count) {
                     if (!types_are_compatible(t1->Function.params[i], t2->Function.params[i])) return 0;
                 }
             }
@@ -232,7 +230,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             func_type->Function.return_type = type_build_from_ast(alloc, ftype_node->return_type);
 
             if (param_count > 0)
-                fori (i, 0, param_count - 1) {
+                fori (i, 0, param_count) {
                     func_type->Function.params[i] = type_build_from_ast(alloc, ftype_node->params[i]);
                 }
 
@@ -283,7 +281,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             u32 offset = 0;
             u32 alignment = 1, mem_alignment;
             u32 idx = 0;
-            bh_arr_each(AstStructMember *, member, s_node->members) {
+            bh_arr_each(AstTyped *, member, s_node->members) {
                 (*member)->type = type_build_from_ast(alloc, (*member)->type_node);
 
                 // TODO: Add alignment checking here
@@ -301,13 +299,21 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
 
                 token_toggle_end((*member)->token);
                 bh_table_put(StructMember, s_type->Struct.members, (*member)->token->text, smem);
-                bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, (*member)->token->text));
                 token_toggle_end((*member)->token);
 
                 offset += type_size_of((*member)->type);
                 idx++;
             }
 
+            // NOTE: Need to do a second pass because the references to the
+            // elements of the table may change if the internal arrays of the
+            // table need to be resized.
+            bh_arr_each(AstTyped *, member, s_node->members) {
+                token_toggle_end((*member)->token);
+                bh_arr_push(s_type->Struct.memarr, &bh_table_get(StructMember, s_type->Struct.members, (*member)->token->text));
+                token_toggle_end((*member)->token);
+            }
+
             s_type->Struct.aligment = alignment;
 
             if (offset % alignment != 0) {
index c9ffe68901a306185aacd89b563ffda350458221..fe1de9d3ebe1340f358a8c4e27cd03e9e05b7b95 100644 (file)
@@ -364,6 +364,7 @@ COMPILE_FUNC(local_location,                AstLocal* local, u64* offset_return)
 COMPILE_FUNC(memory_reservation_location,   AstMemRes* memres);
 COMPILE_FUNC(struct_load,                   Type* type, u64 offset);
 COMPILE_FUNC(struct_store,                  AstTyped* lval);
+COMPILE_FUNC(struct_literal,                AstStructLiteral* sl);
 COMPILE_FUNC(expression,                    AstTyped* expr);
 COMPILE_FUNC(cast,                          AstUnaryOp* cast);
 COMPILE_FUNC(return,                        AstReturn* ret);
@@ -1151,6 +1152,16 @@ COMPILE_FUNC(struct_store, AstTyped* lval) {
     *pcode = code;
 }
 
+COMPILE_FUNC(struct_literal, AstStructLiteral* sl) {
+    bh_arr(WasmInstruction) code = *pcode;
+
+    bh_arr_each(AstTyped *, val, sl->values) {
+        compile_expression(mod, &code, *val);
+    }
+
+    *pcode = code;
+}
+
 COMPILE_FUNC(expression, AstTyped* expr) {
     bh_arr(WasmInstruction) code = *pcode;
 
@@ -1221,6 +1232,11 @@ COMPILE_FUNC(expression, AstTyped* expr) {
             break;
         }
 
+        case Ast_Kind_Struct_Literal: {
+            compile_struct_literal(mod, &code, (AstStructLiteral *) expr);
+            break;
+        }
+
         case Ast_Kind_Function: {
             i32 elemidx = get_element_idx(mod, (AstFunction *) expr);
             WID(WI_I32_CONST, elemidx);
@@ -2610,7 +2626,7 @@ static i32 output_datasection(OnyxWasmModule* module, bh_buffer* buff) {
 
         leb = uint_to_uleb128((u64) datum->length, &leb_len);
         bh_buffer_append(&vec_buff, leb, leb_len);
-        fori (i, 0, datum->length - 1) bh_buffer_write_byte(&vec_buff, ((u8 *) datum->data)[i]);
+        fori (i, 0, datum->length) bh_buffer_write_byte(&vec_buff, ((u8 *) datum->data)[i]);
     }
 
     leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);