Added simple array mechanics; Cleaned up code in the process
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 17 Jul 2020 22:08:05 +0000 (17:08 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 17 Jul 2020 22:08:05 +0000 (17:08 -0500)
13 files changed:
.vimspector.json
include/bh.h
include/onyxastnodes.h
onyx
progs/arrays.onyx [new file with mode: 0644]
progs/basic.onyx
progs/intrinsics.onyx
src/onyxchecker.c
src/onyxmsgs.c
src/onyxparser.c
src/onyxsymres.c
src/onyxutils.c
src/onyxwasm.c

index 88493853a3314d6b6d7717d1fe5c86193f4b554c..404230c70b10b310d524800b812d6deafcae12bb 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["progs/basic.onyx"],
+                "args": ["progs/arrays.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index e443f27bdd4b8dd7d243aa078972be323df0d69a..4b1b07b5f7af15fe0532619ba6f75fcf38f1faf3 100644 (file)
@@ -94,12 +94,32 @@ inline i64 chars_match(char* ptr1, char* ptr2) {
 //-------------------------------------------------------------------------------------
 // Better math functions
 //-------------------------------------------------------------------------------------
-#define bh_max(a, b)        ((a) > (b) ? (a) : (b))
-#define bh_min(a, b)        ((a) < (b) ? (a) : (b))
+#define bh_max(a, b)         ((a) > (b) ? (a) : (b))
+#define bh_min(a, b)         ((a) < (b) ? (a) : (b))
 #define bh_clamp(v, a, b)    (bh_min((b), bh_max((a), (v))))
 #define bh_abs(x)            ((x) < 0 ? -(x) : (x))
 
-
+static inline u64 log2_dumb(u64 n) {
+    switch (n) {
+    case 1:    return 0;
+    case 2:    return 1;
+    case 4:    return 2;
+    case 8:    return 3;
+    case 16:   return 4;
+    case 32:   return 5;
+    case 64:   return 6;
+    case 128:  return 7;
+    case 256:  return 8;
+    case 512:  return 9;
+    case 1024: return 10;
+    case 2048: return 11;
+    case 4096: return 12;
+    case 8192: return 13;
+
+    // Don't need all of them right now
+    default:   return 0;
+    }
+}
 
 
 
index 1d2293b1fff190a564fe01e1b3ef7ef665007b5a..6e3a2366bf94c0a271e2ec84a667feecb65b0b9c 100644 (file)
@@ -6,15 +6,18 @@
 
 typedef struct AstNode AstNode;
 typedef struct AstTyped AstTyped;
-typedef struct AstUnaryOp AstUnaryOp;
+
 typedef struct AstBinOp AstBinaryOp;
-typedef struct AstAssign AstAssign;
+typedef struct AstUnaryOp AstUnaryOp;
 typedef struct AstNumLit AstNumLit;
 typedef struct AstLocal AstLocal;
-typedef struct AstReturn AstReturn;
 typedef struct AstCall AstCall;
 typedef struct AstIntrinsicCall AstIntrinsicCall;
 typedef struct AstArgument AstArgument;
+typedef struct AstArrayAccess AstArrayAccess;
+
+typedef struct AstAssign AstAssign;
+typedef struct AstReturn AstReturn;
 
 typedef struct AstBlock AstBlock;
 typedef struct AstIf AstIf;
@@ -61,8 +64,8 @@ typedef enum AstKind {
     Ast_Kind_Argument,
     Ast_Kind_Call,
     Ast_Kind_Intrinsic_Call,
-    Ast_Kind_Assignment,
     Ast_Kind_Return,
+    Ast_Kind_Array_Access,
 
     Ast_Kind_If,
     Ast_Kind_While,
@@ -77,14 +80,16 @@ typedef enum AstKind {
 typedef enum AstFlags {
     // Top-level flags
     Ast_Flag_Exported        = BH_BIT(0),
-    Ast_Flag_Lval            = BH_BIT(1),
+    Ast_Flag_Foreign         = BH_BIT(1),
     Ast_Flag_Const           = BH_BIT(2),
     Ast_Flag_Comptime        = BH_BIT(3),
 
     // Function flags
     Ast_Flag_Inline          = BH_BIT(8),
     Ast_Flag_Intrinsic       = BH_BIT(9),
-    Ast_Flag_Foreign         = BH_BIT(10),
+
+    // Expression flags
+    Ast_Flag_Expr_Ignored    = BH_BIT(8),
 } AstFlags;
 
 typedef enum UnaryOp {
@@ -94,20 +99,57 @@ typedef enum UnaryOp {
 } UnaryOp;
 
 typedef enum BinaryOp {
-    Binary_Op_Add           = 0,
-    Binary_Op_Minus         = 1,
-    Binary_Op_Multiply      = 2,
-    Binary_Op_Divide        = 3,
-    Binary_Op_Modulus       = 4,
-
-    Binary_Op_Equal         = 5,
-    Binary_Op_Not_Equal     = 6,
-    Binary_Op_Less          = 7,
-    Binary_Op_Less_Equal    = 8,
-    Binary_Op_Greater       = 9,
-    Binary_Op_Greater_Equal = 10,
+    Binary_Op_Add             = 0,
+    Binary_Op_Minus           = 1,
+    Binary_Op_Multiply        = 2,
+    Binary_Op_Divide          = 3,
+    Binary_Op_Modulus         = 4,
+
+    Binary_Op_Equal           = 5,
+    Binary_Op_Not_Equal       = 6,
+    Binary_Op_Less            = 7,
+    Binary_Op_Less_Equal      = 8,
+    Binary_Op_Greater         = 9,
+    Binary_Op_Greater_Equal   = 10,
+
+    Binary_Op_Assign_Start    = 11,
+    Binary_Op_Assign          = 12,
+    Binary_Op_Assign_Add      = 13,
+    Binary_Op_Assign_Minus    = 14,
+    Binary_Op_Assign_Multiply = 15,
+    Binary_Op_Assign_Divide   = 16,
+    Binary_Op_Assign_Modulus  = 17,
+    Binary_Op_Assign_End      = 18,
 } BinaryOp;
 
+typedef enum OnyxIntrinsic {
+    ONYX_INTRINSIC_UNDEFINED,
+
+    ONYX_INTRINSIC_MEMORY_SIZE, ONYX_INTRINSIC_MEMORY_GROW,
+
+    ONYX_INTRINSIC_I32_CLZ,   ONYX_INTRINSIC_I32_CTZ, ONYX_INTRINSIC_I32_POPCNT,
+    ONYX_INTRINSIC_I32_AND,   ONYX_INTRINSIC_I32_OR,  ONYX_INTRINSIC_I32_XOR,
+    ONYX_INTRINSIC_I32_SHL,   ONYX_INTRINSIC_I32_SLR, ONYX_INTRINSIC_I32_SAR,
+    ONYX_INTRINSIC_I32_ROTL,  ONYX_INTRINSIC_I32_ROTR,
+
+    ONYX_INTRINSIC_I64_CLZ,   ONYX_INTRINSIC_I64_CTZ, ONYX_INTRINSIC_I64_POPCNT,
+    ONYX_INTRINSIC_I64_AND,   ONYX_INTRINSIC_I64_OR,  ONYX_INTRINSIC_I64_XOR,
+    ONYX_INTRINSIC_I64_SHL,   ONYX_INTRINSIC_I64_SLR, ONYX_INTRINSIC_I64_SAR,
+    ONYX_INTRINSIC_I64_ROTL,  ONYX_INTRINSIC_I64_ROTR,
+
+    ONYX_INTRINSIC_F32_ABS,   ONYX_INTRINSIC_F32_SQRT,
+    ONYX_INTRINSIC_F32_CEIL,  ONYX_INTRINSIC_F32_FLOOR,
+    ONYX_INTRINSIC_F32_TRUNC, ONYX_INTRINSIC_F32_NEAREST,
+    ONYX_INTRINSIC_F32_MIN,   ONYX_INTRINSIC_F32_MAX,
+    ONYX_INTRINSIC_F32_COPYSIGN,
+
+    ONYX_INTRINSIC_F64_ABS,   ONYX_INTRINSIC_F64_SQRT,
+    ONYX_INTRINSIC_F64_CEIL,  ONYX_INTRINSIC_F64_FLOOR,
+    ONYX_INTRINSIC_F64_TRUNC, ONYX_INTRINSIC_F64_NEAREST,
+    ONYX_INTRINSIC_F64_MIN,   ONYX_INTRINSIC_F64_MAX,
+    ONYX_INTRINSIC_F64_COPYSIGN,
+} OnyxIntrinsic;
+
 
 // Base Nodes
 #define AstNode_members {     \
@@ -141,12 +183,15 @@ struct AstTyped AstTyped_members;
 // Expression Nodes
 struct AstBinOp         { AstTyped_base; BinaryOp operation; AstTyped *left, *right; };
 struct AstUnaryOp       { AstTyped_base; UnaryOp operation; AstTyped *expr; };
-struct AstAssign        { AstNode_base;  AstTyped* lval; AstTyped* expr; };
 struct AstNumLit        { AstTyped_base; union { i32 i; i64 l; f32 f; f64 d; } value; };
 struct AstLocal         { AstTyped_base; AstLocal *prev_local; };
-struct AstReturn        { AstNode_base;  AstTyped* expr; };
 struct AstCall          { AstTyped_base; AstArgument *arguments; AstNode *callee; };
+struct AstIntrinsicCall { AstTyped_base; AstArgument *arguments; OnyxIntrinsic intrinsic; };
 struct AstArgument      { AstTyped_base; AstTyped *value; };
+struct AstArrayAccess   { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 elem_size; };
+
+// Intruction Node
+struct AstReturn        { AstNode_base;  AstTyped* expr; };
 
 // Structure Nodes
 struct AstLocalGroup    { AstNode_base;  AstLocalGroup *prev_group; AstLocal *last_local; };
@@ -211,38 +256,6 @@ struct AstFunction      {
     };
 };
 
-typedef enum OnyxIntrinsic {
-    ONYX_INTRINSIC_UNDEFINED,
-
-    ONYX_INTRINSIC_MEMORY_SIZE, ONYX_INTRINSIC_MEMORY_GROW,
-
-    ONYX_INTRINSIC_I32_CLZ,   ONYX_INTRINSIC_I32_CTZ, ONYX_INTRINSIC_I32_POPCNT,
-    ONYX_INTRINSIC_I32_AND,   ONYX_INTRINSIC_I32_OR,  ONYX_INTRINSIC_I32_XOR,
-    ONYX_INTRINSIC_I32_SHL,   ONYX_INTRINSIC_I32_SLR, ONYX_INTRINSIC_I32_SAR,
-    ONYX_INTRINSIC_I32_ROTL,  ONYX_INTRINSIC_I32_ROTR,
-
-    ONYX_INTRINSIC_I64_CLZ,   ONYX_INTRINSIC_I64_CTZ, ONYX_INTRINSIC_I64_POPCNT,
-    ONYX_INTRINSIC_I64_AND,   ONYX_INTRINSIC_I64_OR,  ONYX_INTRINSIC_I64_XOR,
-    ONYX_INTRINSIC_I64_SHL,   ONYX_INTRINSIC_I64_SLR, ONYX_INTRINSIC_I64_SAR,
-    ONYX_INTRINSIC_I64_ROTL,  ONYX_INTRINSIC_I64_ROTR,
-
-    ONYX_INTRINSIC_F32_ABS,   ONYX_INTRINSIC_F32_SQRT,
-    ONYX_INTRINSIC_F32_CEIL,  ONYX_INTRINSIC_F32_FLOOR,
-    ONYX_INTRINSIC_F32_TRUNC, ONYX_INTRINSIC_F32_NEAREST,
-    ONYX_INTRINSIC_F32_MIN,   ONYX_INTRINSIC_F32_MAX,
-    ONYX_INTRINSIC_F32_COPYSIGN,
-
-    ONYX_INTRINSIC_F64_ABS,   ONYX_INTRINSIC_F64_SQRT,
-    ONYX_INTRINSIC_F64_CEIL,  ONYX_INTRINSIC_F64_FLOOR,
-    ONYX_INTRINSIC_F64_TRUNC, ONYX_INTRINSIC_F64_NEAREST,
-    ONYX_INTRINSIC_F64_MIN,   ONYX_INTRINSIC_F64_MAX,
-    ONYX_INTRINSIC_F64_COPYSIGN,
-} OnyxIntrinsic;
-
-// NOTE: This needs to have 'arguments' in the
-// same position as AstNodeCall
-struct AstIntrinsicCall { AstTyped_base; AstArgument *arguments; OnyxIntrinsic intrinsic; };
-
 // NOTE: Simple data structure for storing what comes out of the parser
 typedef struct ParserOutput {
     bh_arr(AstBinding *)  top_level_bindings;
@@ -271,4 +284,17 @@ extern AstBasicType basic_type_f32;
 extern AstBasicType basic_type_f64;
 extern AstBasicType basic_type_rawptr;
 
+
+// NOTE: Useful inlined functions
+static inline b32 is_lval(AstNode* node) {
+    return (node->kind == Ast_Kind_Local)
+        || (node->kind == Ast_Kind_Global)
+        || (node->kind == Ast_Kind_Array_Access);
+}
+
+static inline b32 binop_is_assignment(AstBinaryOp* binop) {
+    return (binop->operation >= Binary_Op_Assign_Start
+            && binop->operation <= Binary_Op_Assign_End);
+}
+
 #endif // #ifndef ONYXASTNODES_H
diff --git a/onyx b/onyx
index 8457bd029fef3350cbd6cc053d59c4ee343b972d..a645223c29179f5a3ad75a93ad2e4700b062c1bb 100755 (executable)
Binary files a/onyx and b/onyx differ
diff --git a/progs/arrays.onyx b/progs/arrays.onyx
new file mode 100644 (file)
index 0000000..0db8ba9
--- /dev/null
@@ -0,0 +1,23 @@
+use "progs/intrinsics"
+use "progs/print_funcs"
+
+main :: proc #export {
+    print_i32(memory_size());
+
+    arr := 0 as ^i64;
+
+    arr[0] = 10 as i64;
+    arr[1] = 20 as i64;
+    arr[2] = 30 as i64;
+    arr[3] = 40 as i64;
+
+    i := 0;
+    while i < 4 {
+        arr[i] += 1 as i64;
+        arr[i] *= 2 as i64;
+
+        print_i64(arr[i]);
+        i += 1;
+    }
+}
+
index caed8770263ebda4239b109b3996c4c2c4f7641b..5b9de01f56e1e815845da9e3d54ef05e5636d2a2 100644 (file)
@@ -31,7 +31,7 @@ global_value :: 5 * 2 + 6
 wasm_global :: global i32
 
 main :: proc #export {
-    a := 16;
+    a : i32 = 16;
     print(clz_i32(a));
 
     wasm_global = 5 + global_value;
@@ -40,7 +40,7 @@ main :: proc #export {
     print(4 + global_value);
 
     b := 1 + foo(2);
-    if b == 13 b = 10;
+    if b == 13 b += 10;
     print(b);
 
     if b == 13 print(5678);
index ceece40f863fe4a77db207f369b2baa36d12c948..cb4fce4ddc8e9c447e8947237fe416249cd923ad 100644 (file)
@@ -1,5 +1,5 @@
 memory_size  :: proc #intrinsic -> i32 ---
-memory_grow  :: proc #intrinsic -> i32 ---
+memory_grow  :: proc #intrinsic (val: i32) -> i32 ---
 
 clz_i32      :: proc #intrinsic (val: i32) -> i32 ---
 ctz_i32      :: proc #intrinsic (val: i32) -> i32 ---
index ec81e35f58d9691ff90dd3212a22a954c63a574e..97b18cb70b1e14ef627acff14d99c07d417b8ed0 100644 (file)
@@ -1,66 +1,20 @@
 #define BH_DEBUG
 #include "onyxsempass.h"
+#include "onyxparser.h"
 
 static b32 check_function(SemState* state, AstFunction* func);
 static b32 check_block(SemState* state, AstBlock* block);
 static b32 check_statement_chain(SemState* state, AstNode* start);
 static b32 check_statement(SemState* state, AstNode* stmt);
-static b32 check_assignment(SemState* state, AstAssign* assign);
 static b32 check_return(SemState* state, AstReturn* retnode);
 static b32 check_if(SemState* state, AstIf* ifnode);
 static b32 check_while(SemState* state, AstWhile* whilenode);
 static b32 check_call(SemState* state, AstCall* call);
 static b32 check_binaryop(SemState* state, AstBinaryOp* binop);
 static b32 check_expression(SemState* state, AstTyped* expr);
+static b32 check_array_access(SemState* state, AstArrayAccess* expr);
 static b32 check_global(SemState* state, AstGlobal* global);
 
-static b32 check_assignment(SemState* state, AstAssign* assign) {
-    if (assign->lval->kind == Ast_Kind_Symbol) {
-        onyx_message_add(state->msgs,
-                ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
-                assign->lval->token->pos,
-                assign->lval->token->text, assign->lval->token->length);
-        return 1;
-    }
-
-    if ((assign->lval->flags & Ast_Flag_Const) != 0 && assign->lval->type != NULL) {
-        onyx_message_add(state->msgs,
-                ONYX_MESSAGE_TYPE_ASSIGN_CONST,
-                assign->token->pos,
-                assign->lval->token->text, assign->lval->token->length);
-        return 1;
-    }
-
-    if ((assign->lval->flags & Ast_Flag_Lval) == 0) {
-        onyx_message_add(state->msgs,
-                ONYX_MESSAGE_TYPE_NOT_LVAL,
-                assign->token->pos,
-                assign->lval->token->text, assign->lval->token->length);
-        return 1;
-    }
-
-    if (assign->lval->type == NULL) {
-        assign->lval->type = type_build_from_ast(state->node_allocator, assign->lval->type_node);
-    }
-
-    if (check_expression(state, assign->expr)) return 1;
-
-    if (assign->lval->type == NULL) {
-        assign->lval->type = assign->expr->type;
-    } else {
-        if (!types_are_compatible(assign->lval->type, assign->expr->type)) {
-            onyx_message_add(state->msgs,
-                    ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH,
-                    assign->token->pos,
-                    type_get_name(assign->lval->type),
-                    type_get_name(assign->expr->type));
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
 static b32 check_return(SemState* state, AstReturn* retnode) {
     if (retnode->expr) {
         if (check_expression(state, retnode->expr)) return 1;
@@ -255,6 +209,63 @@ static b32 check_binaryop(SemState* state, AstBinaryOp* binop) {
     if (check_expression(state, binop->left)) return 1;
     if (check_expression(state, binop->right)) return 1;
 
+    if (binop_is_assignment(binop)) {
+        if (!is_lval((AstNode *) binop->left)) {
+            onyx_message_add(state->msgs,
+                    ONYX_MESSAGE_TYPE_NOT_LVAL,
+                    binop->token->pos,
+                    binop->left->token->text, binop->left->token->length);
+            return 1;
+        }
+
+        if ((binop->left->flags & Ast_Flag_Const) != 0 && binop->left->type != NULL) {
+            onyx_message_add(state->msgs,
+                    ONYX_MESSAGE_TYPE_ASSIGN_CONST,
+                    binop->token->pos,
+                    binop->left->token->text, binop->left->token->length);
+            return 1;
+        }
+
+        if (binop->operation == Binary_Op_Assign) {
+            // NOTE: Raw assignment
+            if (binop->left->type == NULL) {
+                binop->left->type = binop->right->type;
+            }
+
+        } else {
+            // NOTE: +=, -=, ...
+
+            AstBinaryOp* binop_node = onyx_ast_node_new(
+                    state->node_allocator,
+                    sizeof(AstBinaryOp),
+                    Ast_Kind_Binary_Op);
+
+            binop_node->token = binop->token;
+            binop_node->left  = binop->left;
+            binop_node->right = binop->right;
+            binop_node->type  = binop->right->type;
+
+            if      (binop->operation == Binary_Op_Assign_Add)      binop_node->operation = Binary_Op_Add;
+            else if (binop->operation == Binary_Op_Assign_Minus)    binop_node->operation = Binary_Op_Minus;
+            else if (binop->operation == Binary_Op_Assign_Multiply) binop_node->operation = Binary_Op_Multiply;
+            else if (binop->operation == Binary_Op_Assign_Divide)   binop_node->operation = Binary_Op_Divide;
+            else if (binop->operation == Binary_Op_Assign_Modulus)  binop_node->operation = Binary_Op_Modulus;
+
+            binop->right = (AstTyped *) binop_node;
+            binop->operation = Binary_Op_Assign;
+        }
+
+    } else {
+        if (type_is_pointer(binop->left->type)
+                || type_is_pointer(binop->right->type)) {
+            onyx_message_add(state->msgs,
+                    ONYX_MESSAGE_TYPE_LITERAL,
+                    binop->token->pos,
+                    "binary operations are not supported for pointers (yet).");
+            return 1;
+        }
+    }
+
     if (binop->left->type == NULL) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
@@ -271,14 +282,6 @@ static b32 check_binaryop(SemState* state, AstBinaryOp* binop) {
         return 1;
     }
 
-    if (type_is_pointer(binop->left->type)
-            || type_is_pointer(binop->right->type)) {
-        onyx_message_add(state->msgs,
-                ONYX_MESSAGE_TYPE_LITERAL,
-                binop->token->pos,
-                "binary operations are not supported for pointers (yet).");
-        return 1;
-    }
 
     if (!types_are_compatible(binop->left->type, binop->right->type)) {
         onyx_message_add(state->msgs,
@@ -299,6 +302,33 @@ static b32 check_binaryop(SemState* state, AstBinaryOp* binop) {
     return 0;
 }
 
+static b32 check_array_access(SemState* state, AstArrayAccess* aa) {
+    check_expression(state, aa->addr);
+    check_expression(state, aa->expr);
+
+    if (!type_is_pointer(aa->addr->type)) {
+        onyx_message_add(state->msgs,
+                ONYX_MESSAGE_TYPE_LITERAL,
+                aa->addr->token->pos,
+                "expected pointer type for left of array access");
+        return 1;
+    }
+
+    if (aa->expr->type->kind != Type_Kind_Basic
+            || (aa->expr->type->Basic.flags & Basic_Flag_Integer) == 0) {
+        onyx_message_add(state->msgs,
+                ONYX_MESSAGE_TYPE_LITERAL,
+                aa->expr->token->pos,
+                "expected integer type for index");
+        return 1;
+    }
+
+    aa->type = aa->addr->type->Pointer.elem;
+    aa->elem_size = aa->type->Basic.size;
+
+    return 0;
+}
+
 static b32 check_expression(SemState* state, AstTyped* expr) {
     if (expr->kind > Ast_Kind_Type_Start && expr->kind < Ast_Kind_Type_End) {
         onyx_message_add(state->msgs,
@@ -335,7 +365,6 @@ static b32 check_expression(SemState* state, AstTyped* expr) {
             retval = 1;
             break;
 
-        case Ast_Kind_Local:
         case Ast_Kind_Param:
             if (expr->type == NULL) {
                 onyx_message_add(state->msgs,
@@ -346,6 +375,12 @@ static b32 check_expression(SemState* state, AstTyped* expr) {
             }
             break;
 
+        case Ast_Kind_Local: break;
+
+        case Ast_Kind_Array_Access:
+            retval = check_array_access(state, (AstArrayAccess *) expr);
+            break;
+
         case Ast_Kind_Global:
             if (expr->type == NULL) {
                 onyx_message_add(state->msgs,
@@ -397,14 +432,15 @@ static b32 check_global(SemState* state, AstGlobal* global) {
 
 static b32 check_statement(SemState* state, AstNode* stmt) {
     switch (stmt->kind) {
-        case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) stmt);
         case Ast_Kind_Return:     return check_return(state, (AstReturn *) stmt);
         case Ast_Kind_If:         return check_if(state, (AstIf *) stmt);
         case Ast_Kind_While:      return check_while(state, (AstWhile *) stmt);
         case Ast_Kind_Call:       return check_call(state, (AstCall *) stmt);
         case Ast_Kind_Block:      return check_block(state, (AstBlock *) stmt);
 
-        default: return 0;
+        default:
+            stmt->flags |= Ast_Flag_Expr_Ignored;
+            return check_expression(state, (AstTyped *) stmt);
     }
 }
 
@@ -506,7 +542,6 @@ static b32 check_node(SemState* state, AstNode* node) {
     switch (node->kind) {
         case Ast_Kind_Function:     return check_function(state, (AstFunction *) node);
         case Ast_Kind_Block:        return check_block(state, (AstBlock *) node);
-        case Ast_Kind_Assignment:   return check_assignment(state, (AstAssign *) node);
         case Ast_Kind_Return:       return check_return(state, (AstReturn *) node);
         case Ast_Kind_If:           return check_if(state, (AstIf *) node);
         case Ast_Kind_While:        return check_while(state, (AstWhile *) node);
index 5b1d8c57cf3f6c7874fd6f8f8b8e259ce5dba4cf..f7a6e52b4152232ecdcfb3e0b79156fd41a08dda 100644 (file)
@@ -2,7 +2,7 @@
 #include "onyxmsgs.h"
 #include "onyxutils.h"
 
-#define MAX_MSGS 5
+#define MAX_MSGS 10
 
 static const char* msg_formats[] = {
     "%s",
index d98a8c6eb5bf3151b168702ad88d9c40d07b8d74..85c1d75381a630336ace6f28ed427ec462f5fc01 100644 (file)
@@ -33,7 +33,7 @@ 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 b32          parse_symbol_statement(OnyxParser* parser, AstNode** ret);
+static b32          parse_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);
@@ -256,6 +256,17 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             return NULL;
     }
 
+    while (parser->curr->type == '[') {
+        AstArrayAccess* aa_node = make_node(AstArrayAccess, Ast_Kind_Array_Access);
+        aa_node->token = expect_token(parser, '[');
+        aa_node->addr  = retval;
+        aa_node->expr  = parse_expression(parser);
+
+        expect_token(parser, ']');
+
+        retval = (AstTyped *) aa_node;
+    }
+
     while (parser->curr->type == Token_Type_Keyword_Cast) {
         consume_token(parser);
 
@@ -266,41 +277,56 @@ static AstTyped* parse_factor(OnyxParser* parser) {
         retval = (AstTyped *) cast_node;
     }
 
+
     return retval;
 }
 
 static inline i32 get_precedence(BinaryOp kind) {
     switch (kind) {
-        case Binary_Op_Equal: return 3;
-        case Binary_Op_Not_Equal: return 3;
+        case Binary_Op_Assign:          return 2;
+        case Binary_Op_Assign_Add:      return 2;
+        case Binary_Op_Assign_Minus:    return 2;
+        case Binary_Op_Assign_Multiply: return 2;
+        case Binary_Op_Assign_Divide:   return 2;
+        case Binary_Op_Assign_Modulus:  return 2;
+
+        case Binary_Op_Equal:           return 3;
+        case Binary_Op_Not_Equal:       return 3;
+
+        case Binary_Op_Less_Equal:      return 4;
+        case Binary_Op_Less:            return 4;
+        case Binary_Op_Greater_Equal:   return 4;
+        case Binary_Op_Greater:         return 4;
 
-        case Binary_Op_Less_Equal: return 4;
-        case Binary_Op_Less: return 4;
-        case Binary_Op_Greater_Equal: return 4;
-        case Binary_Op_Greater: return 4;
+        case Binary_Op_Add:             return 5;
+        case Binary_Op_Minus:           return 5;
 
-        case Binary_Op_Add: return 5;
-        case Binary_Op_Minus: return 5;
+        case Binary_Op_Multiply:        return 6;
+        case Binary_Op_Divide:          return 6;
 
-        case Binary_Op_Multiply: return 6;
-        case Binary_Op_Divide: return 6;
+        case Binary_Op_Modulus:         return 7;
 
-        case Binary_Op_Modulus: return 7;
-        default: return -1;
+        default:                        return -1;
     }
 }
 
-// <factor> + <factor>
-// <factor> - <factor>
-// <factor> * <factor>
-// <factor> / <factor>
-// <factor> % <factor>
-// <factor> == <factor>
-// <factor> != <factor>
-// <factor> <= <factor>
-// <factor> >= <factor>
-// <factor> < <factor>
-// <factor> > <factor>
+// <expr> +  <expr>
+// <expr> -  <expr>
+// <expr> *  <expr>
+// <expr> /  <expr>
+// <expr> %  <expr>
+// <expr> == <expr>
+// <expr> != <expr>
+// <expr> <= <expr>
+// <expr> >= <expr>
+// <expr> <  <expr>
+// <expr> >  <expr>
+// <expr> =  <expr>
+// <expr> += <expr>
+// <expr> -= <expr>
+// <expr> *= <expr>
+// <expr> /= <expr>
+// <expr> %= <expr>
 // With expected precedence rules
 static AstTyped* parse_expression(OnyxParser* parser) {
     bh_arr(AstBinaryOp*) tree_stack = NULL;
@@ -329,6 +355,13 @@ static AstTyped* parse_expression(OnyxParser* parser) {
             case '*':                       bin_op_kind = Binary_Op_Multiply; break;
             case '/':                       bin_op_kind = Binary_Op_Divide; break;
             case '%':                       bin_op_kind = Binary_Op_Modulus; break;
+
+            case '=':                       bin_op_kind = Binary_Op_Assign; break;
+            case Token_Type_Plus_Equal:     bin_op_kind = Binary_Op_Assign_Add; break;
+            case Token_Type_Minus_Equal:    bin_op_kind = Binary_Op_Assign_Minus; break;
+            case Token_Type_Star_Equal:     bin_op_kind = Binary_Op_Assign_Multiply; break;
+            case Token_Type_Fslash_Equal:   bin_op_kind = Binary_Op_Assign_Divide; break;
+            case Token_Type_Percent_Equal:  bin_op_kind = Binary_Op_Assign_Modulus; break;
             default: goto expression_done;
         }
 
@@ -429,125 +462,54 @@ static AstWhile* parse_while_stmt(OnyxParser* parser) {
 // <symbol> : <type> : <expr>
 // <symbol> := <expr>
 // <symbol> :: <expr>
-// <symbol> = <expr>
-// <symbol> += <expr>
-// <symbol> -= <expr>
-// <symbol> *= <expr>
-// <symbol> /= <expr>
-// <symbol> %= <expr>
-static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) {
+static b32 parse_symbol_declaration(OnyxParser* parser, AstNode** ret) {
     if (parser->curr->type != Token_Type_Symbol) return 0;
-    OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
-
-    switch ((u16) parser->curr->type) {
-        // NOTE: Declaration
-        case ':':
-            {
-                consume_token(parser);
-                AstType* type_node = NULL;
-
-                // NOTE: var: type
-                if (parser->curr->type != ':'
-                        && parser->curr->type != '=') {
-                    type_node = parse_type(parser);
-                }
-
-                AstLocal* local = make_node(AstLocal, Ast_Kind_Local);
-                local->token = symbol;
-                local->type_node = type_node;
-                local->flags |= Ast_Flag_Lval; // NOTE: DELETE
-                *ret = (AstNode *) local;
-
-                if (parser->curr->type == '=' || parser->curr->type == ':') {
-                    if (parser->curr->type == ':') {
-                        local->flags |= Ast_Flag_Const;
-                    }
-
-                    AstAssign* assignment = make_node(AstAssign, Ast_Kind_Assignment);
-                    local->next = (AstNode *) assignment;
-                    assignment->token = parser->curr;
-                    consume_token(parser);
-
-                    AstTyped* expr = parse_expression(parser);
-                    if (expr == NULL) {
-                        token_toggle_end(parser->curr);
-                        onyx_message_add(parser->msgs,
-                                ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
-                                assignment->token->pos,
-                                parser->curr->text);
-                        token_toggle_end(parser->curr);
-                        return 1;
-                    }
-                    assignment->expr = expr;
-
-                    AstNode* left_symbol = make_node(AstNode, Ast_Kind_Symbol);
-                    left_symbol->token = symbol;
-                    assignment->lval = (AstTyped *) left_symbol;
-                }
-                return 1;
-            }
-
-            // NOTE: Assignment
-        case '=':
-            {
-                AstAssign* assignment = make_node(AstAssign, Ast_Kind_Assignment);
-                assignment->token = parser->curr;
-                consume_token(parser);
-
-                AstNode* lval = make_node(AstNode, Ast_Kind_Symbol);
-                lval->token = symbol;
-
-                AstTyped* rval = parse_expression(parser);
-                assignment->expr = rval;
-                assignment->lval = (AstTyped *) lval;
-                *ret = (AstNode *) assignment;
-                return 1;
-            }
+    if ((parser->curr + 1)->type != ':')         return 0;
 
-        case Token_Type_Plus_Equal:
-        case Token_Type_Minus_Equal:
-        case Token_Type_Star_Equal:
-        case Token_Type_Fslash_Equal:
-        case Token_Type_Percent_Equal:
-            {
-                BinaryOp bin_op;
-                if      (parser->curr->type == Token_Type_Plus_Equal)    bin_op = Binary_Op_Add;
-                else if (parser->curr->type == Token_Type_Minus_Equal)   bin_op = Binary_Op_Minus;
-                else if (parser->curr->type == Token_Type_Star_Equal)    bin_op = Binary_Op_Multiply;
-                else if (parser->curr->type == Token_Type_Fslash_Equal)  bin_op = Binary_Op_Divide;
-                else if (parser->curr->type == Token_Type_Percent_Equal) bin_op = Binary_Op_Modulus;
-
-                AstBinaryOp* bin_op_node = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
-                bin_op_node->operation = bin_op;
-                bin_op_node->token = parser->curr;
-
-                consume_token(parser);
-                AstTyped* expr = parse_expression(parser);
+    OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
+    consume_token(parser);
+    AstType* type_node = NULL;
 
-                AstNode* bin_op_left = make_node(AstNode, Ast_Kind_Symbol);
-                bin_op_left->token = symbol;
-                bin_op_node->left = (AstTyped *) bin_op_left;
-                bin_op_node->right = expr;
+    // NOTE: var: type
+    if (parser->curr->type != ':'
+            && parser->curr->type != '=') {
+        type_node = parse_type(parser);
+    }
 
-                AstAssign* assign_node = make_node(AstAssign, Ast_Kind_Assignment);
-                assign_node->token = bin_op_node->token;
+    AstLocal* local = make_node(AstLocal, Ast_Kind_Local);
+    local->token = symbol;
+    local->type_node = type_node;
+    *ret = (AstNode *) local;
 
-                // TODO: Maybe I don't need to make another lval node?
-                AstNode* lval = make_node(AstNode, Ast_Kind_Symbol);
-                lval->token = symbol;
-                assign_node->lval = (AstTyped *) lval;
-                assign_node->expr = (AstTyped *) bin_op_node;
+    if (parser->curr->type == '=' || parser->curr->type == ':') {
+        if (parser->curr->type == ':') {
+            local->flags |= Ast_Flag_Const;
+        }
 
-                *ret = (AstNode *) assign_node;
+        AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
+        assignment->operation = Binary_Op_Assign;
+        local->next = (AstNode *) assignment;
+        assignment->token = parser->curr;
+        consume_token(parser);
 
-                return 1;
-            }
+        AstTyped* expr = parse_expression(parser);
+        if (expr == NULL) {
+            token_toggle_end(parser->curr);
+            onyx_message_add(parser->msgs,
+                    ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
+                    assignment->token->pos,
+                    parser->curr->text);
+            token_toggle_end(parser->curr);
+            return 1;
+        }
+        assignment->right = expr;
 
-        default:
-            unconsume_token(parser);
+        AstNode* left_symbol = make_node(AstNode, Ast_Kind_Symbol);
+        left_symbol->token = symbol;
+        assignment->left = (AstTyped *) left_symbol;
     }
 
-    return 0;
+    return 1;
 }
 
 // 'return' <expr>?
@@ -594,7 +556,7 @@ static AstNode* parse_statement(OnyxParser* parser) {
             break;
 
         case Token_Type_Symbol:
-            if (parse_symbol_statement(parser, &retval)) break;
+            if (parse_symbol_declaration(parser, &retval)) break;
             // fallthrough
 
         case '(':
@@ -894,8 +856,6 @@ static AstTyped* parse_global_declaration(OnyxParser* parser) {
     }
 
     global_node->type_node = parse_type(parser);
-    global_node->flags |= Ast_Flag_Lval;
-
 
     bh_arr_push(parser->results.nodes_to_process, (AstNode *) global_node);
 
index a75c15ccd662b5ab5f99d6fa083008821de86df9..58f988bd210dbeefa8e2655eaa989932c024d11a 100644 (file)
@@ -13,7 +13,6 @@ static AstType* symres_type(SemState* state, AstType* type);
 static void symres_local(SemState* state, AstLocal** local);
 static void symres_call(SemState* state, AstCall* call);
 static void symres_expression(SemState* state, AstTyped** expr);
-static void symres_assignment(SemState* state, AstAssign* assign);
 static void symres_return(SemState* state, AstReturn* ret);
 static void symres_if(SemState* state, AstIf* ifnode);
 static void symres_while(SemState* state, AstWhile* whilenode);
@@ -222,20 +221,17 @@ static void symres_expression(SemState* state, AstTyped** expr) {
             (*expr)->type_node = symres_type(state, (*expr)->type_node);
             break;
 
+        case Ast_Kind_Array_Access:
+            symres_expression(state, &((AstArrayAccess *)(*expr))->addr);
+            symres_expression(state, &((AstArrayAccess *)(*expr))->expr);
+            break;
+
         default:
             DEBUG_HERE;
             break;
     }
 }
 
-static void symres_assignment(SemState* state, AstAssign* assign) {
-    AstTyped* lval = (AstTyped *) symbol_resolve(state, assign->lval->token);
-    if (lval == NULL) return;
-    assign->lval = lval;
-
-    symres_expression(state, &assign->expr);
-}
-
 static void symres_return(SemState* state, AstReturn* ret) {
     if (ret->expr)
         symres_expression(state, &ret->expr);
@@ -263,7 +259,6 @@ static void symres_while(SemState* state, AstWhile* whilenode) {
 static b32 symres_statement(SemState* state, AstNode* stmt) {
     switch (stmt->kind) {
         case Ast_Kind_Local:      symres_local(state, (AstLocal **) &stmt);                return 1;
-        case Ast_Kind_Assignment: symres_assignment(state, (AstAssign *) stmt);            return 0;
         case Ast_Kind_Return:     symres_return(state, (AstReturn *) stmt);                return 0;
         case Ast_Kind_If:         symres_if(state, (AstIf *) stmt);                        return 0;
         case Ast_Kind_While:      symres_while(state, (AstWhile *) stmt);                  return 0;
@@ -271,7 +266,10 @@ static b32 symres_statement(SemState* state, AstNode* stmt) {
         case Ast_Kind_Argument:   symres_expression(state, (AstTyped **) &((AstArgument *)stmt)->value); return 0;
         case Ast_Kind_Block:      symres_block(state, (AstBlock *) stmt);                  return 0;
 
-        default: return 0;
+        case Ast_Kind_Break:      return 0;
+        case Ast_Kind_Continue:   return 0;
+
+        default:                  symres_expression(state, (AstTyped **) &stmt);           return 0;
     }
 }
 
index 098813745acdda5f5f7d50d565dc4c7985c82e2c..d45042ee10f678bbe9091745f08151822b3fdd5a 100644 (file)
@@ -35,8 +35,8 @@ static const char* ast_node_names[] = {
     "PARAM",
     "ARGUMENT",
     "CALL",
-    "ASSIGN",
     "RETURN",
+    "ARRAY_ACCESS",
 
     "IF",
     "WHILE",
index 721cbc0f2a7025e2f148ea6a8e0155f93d3239c8..cccb53c56301f70879dc5f992e22ee58dd1d95ba 100644 (file)
@@ -217,15 +217,14 @@ static WasmType onyx_type_to_wasm_type(Type* type) {
     return WASM_TYPE_VOID;
 }
 
-#define WI(instr) bh_arr_push(code, ((WasmInstruction){ instr, 0x00 }));
-#define WID(instr, data) bh_arr_push(code, ((WasmInstruction){ instr, data }));
+#define WI(instr) bh_arr_push(code, ((WasmInstruction){ instr, 0x00 }))
+#define WID(instr, data) bh_arr_push(code, ((WasmInstruction){ instr, data }))
 #define COMPILE_FUNC(kind, ...) static void compile_ ## kind (OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, __VA_ARGS__)
 
 COMPILE_FUNC(function_body,  AstFunction* fd);
 COMPILE_FUNC(block,          AstBlock* block);
 COMPILE_FUNC(statement,      AstNode* stmt);
-COMPILE_FUNC(assign_lval,    AstTyped* lval);
-COMPILE_FUNC(assignment,     AstAssign* assign);
+COMPILE_FUNC(assignment,     AstBinaryOp* assign);
 COMPILE_FUNC(if,             AstIf* if_node);
 COMPILE_FUNC(while,          AstWhile* while_node);
 COMPILE_FUNC(binop,          AstBinaryOp* binop);
@@ -297,38 +296,58 @@ COMPILE_FUNC(statement, AstNode* stmt) {
 
     switch (stmt->kind) {
         case Ast_Kind_Return:     compile_return(mod, &code, (AstReturn *) stmt); break;
-        case Ast_Kind_Assignment: compile_assignment(mod, &code, (AstAssign *) stmt); break;
         case Ast_Kind_If:         compile_if(mod, &code, (AstIf *) stmt); break;
         case Ast_Kind_While:      compile_while(mod, &code, (AstWhile *) stmt); break;
         case Ast_Kind_Break:      compile_structured_jump(mod, &code, 0); break;
         case Ast_Kind_Continue:   compile_structured_jump(mod, &code, 1); break;
         case Ast_Kind_Block:      compile_block(mod, &code, (AstBlock *) stmt); break;
-
-        case Ast_Kind_Call:
-        case Ast_Kind_Intrinsic_Call:
-            compile_expression(mod, &code, (AstTyped *) stmt);
-            break;
-
-
-        default: break;
+        default:                  compile_expression(mod, &code, (AstTyped *) stmt); break;
     }
 
     *pcode = code;
 }
 
-COMPILE_FUNC(assign_lval, AstTyped* lval) {
+COMPILE_FUNC(assignment, AstBinaryOp* assign) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    if (lval->kind == Ast_Kind_Local || lval->kind == Ast_Kind_Param) {
+    AstTyped* lval = assign->left;
+
+    if (lval->kind == Ast_Kind_Local) {
         i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) lval);
 
+        compile_expression(mod, &code, assign->right);
         WID(WI_LOCAL_SET, localidx);
 
     } else if (lval->kind == Ast_Kind_Global) {
         i32 globalidx = (i32) bh_imap_get(&mod->global_map, (u64) lval);
 
+        compile_expression(mod, &code, assign->right);
         WID(WI_GLOBAL_SET, globalidx);
 
+    } else if (lval->kind == Ast_Kind_Array_Access) {
+        AstArrayAccess* aa = (AstArrayAccess *) lval;
+        WID(WI_I32_CONST, aa->elem_size);
+        compile_expression(mod, &code, aa->expr);
+        WI(WI_I32_MUL);
+        compile_expression(mod, &code, aa->addr);
+        WI(WI_I32_ADD);
+
+        compile_expression(mod, &code, assign->right);
+
+        i32 store_size = aa->type->Basic.size;
+        i32 is_integer = (aa->type->Basic.flags & Basic_Flag_Integer)
+                      || (aa->type->Basic.flags & Basic_Flag_Pointer);
+
+        if (is_integer) {
+            if      (store_size == 1)   WID(WI_I32_STORE_8,  ((WasmInstructionData) { 0, 0 }));
+            else if (store_size == 2)   WID(WI_I32_STORE_16, ((WasmInstructionData) { 1, 0 }));
+            else if (store_size == 4)   WID(WI_I32_STORE,    ((WasmInstructionData) { 2, 0 }));
+            else if (store_size == 8)   WID(WI_I64_STORE,    ((WasmInstructionData) { 3, 0 }));
+        } else {
+            if      (store_size == 4)   WID(WI_F32_STORE, ((WasmInstructionData) { 2, 0 }));
+            else if (store_size == 8)   WID(WI_F64_STORE, ((WasmInstructionData) { 3, 0 }));
+        }
+
     } else {
         assert(("Invalid lval", 0));
     }
@@ -405,15 +424,6 @@ COMPILE_FUNC(while, AstWhile* while_node) {
     *pcode = code;
 }
 
-COMPILE_FUNC(assignment, AstAssign* assign) {
-    bh_arr(WasmInstruction) code = *pcode;
-
-    compile_expression(mod, &code, assign->expr);
-    compile_assign_lval(mod, &code, assign->lval);
-
-    *pcode = code;
-}
-
 // NOTE: These need to be in the same order as
 // the OnyxBinaryOp enum
 static const WasmInstructionType binop_map[][4] = {
@@ -435,6 +445,12 @@ static const WasmInstructionType binop_map[][4] = {
 COMPILE_FUNC(binop, AstBinaryOp* binop) {
     bh_arr(WasmInstruction) code = *pcode;
 
+    if (binop_is_assignment(binop)) {
+        compile_assignment(mod, &code, binop);
+        *pcode = code;
+        return;
+    }
+
     b32 is_sign_significant = 0;
 
     switch (binop->operation) {
@@ -667,7 +683,6 @@ COMPILE_FUNC(expression, AstTyped* expr) {
 
         case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) expr); break;
 
-
         case Ast_Kind_Call:
             compile_call(mod, &code, (AstCall *) expr);
             break;
@@ -676,9 +691,46 @@ COMPILE_FUNC(expression, AstTyped* expr) {
             compile_intrinsic_call(mod, &code, (AstIntrinsicCall *) expr);
             break;
 
+        case Ast_Kind_Array_Access: {
+            AstArrayAccess* aa = (AstArrayAccess *) expr;
+            WID(WI_I32_CONST, aa->elem_size);
+            compile_expression(mod, &code, aa->expr);
+            WI(WI_I32_MUL);
+            compile_expression(mod, &code, aa->addr);
+            WI(WI_I32_ADD);
+
+            i32 load_size   = aa->type->Basic.size;
+            i32 is_integer  = (aa->type->Basic.flags & Basic_Flag_Integer)
+                           || (aa->type->Basic.flags & Basic_Flag_Pointer);
+            i32 is_unsigned = aa->type->Basic.flags & Basic_Flag_Unsigned;
+
+            WasmInstructionType instr = WI_NOP;
+            i32 alignment = log2_dumb(load_size);
+
+            if (is_integer) {
+                if      (load_size == 1) instr = WI_I32_LOAD_8_S;
+                else if (load_size == 2) instr = WI_I32_LOAD_16_S;
+                else if (load_size == 4) instr = WI_I32_LOAD;
+                else if (load_size == 8) instr = WI_I64_LOAD;
+
+                if (alignment < 4 && is_unsigned) instr += 1;
+            } else {
+                if      (load_size == 4) instr = WI_F32_LOAD;
+                else if (load_size == 8) instr = WI_F64_LOAD;
+            }
+
+            if (instr != WI_NOP) {
+                WID(instr, ((WasmInstructionData) { alignment, 0 }));
+            } else {
+                DEBUG_HERE;
+            }
+
+            break;
+        }
+
         default:
-            DEBUG_HERE;
             bh_printf("Unhandled case: %d\n", expr->kind);
+            DEBUG_HERE;
             assert(0);
     }
 
@@ -1064,6 +1116,23 @@ static i32 output_name(const char* start, i32 length, bh_buffer* buff) {
     return buff->length - prev_len;
 }
 
+static i32 output_limits(i32 min, i32 max, bh_buffer* buff) {
+    i32 leb_len, prev_len = buff->length;
+    u8* leb;
+
+    bh_buffer_write_byte(buff, (max >= 0) ? 0x01 : 0x00);
+
+    leb = uint_to_uleb128((u64) min, &leb_len);
+    bh_buffer_append(buff, leb, leb_len);
+
+    if (max >= 0) {
+        leb = uint_to_uleb128((u64) max, &leb_len);
+        bh_buffer_append(buff, leb, leb_len);
+    }
+
+    return buff->length - prev_len;
+}
+
 static i32 output_functype(WasmFuncType* type, bh_buffer* buff) {
     i32 prev_len = buff->length;
 
@@ -1133,6 +1202,28 @@ static i32 output_funcsection(OnyxWasmModule* module, bh_buffer* buff) {
     return buff->length - prev_len;
 }
 
+static i32 output_memorysection(OnyxWasmModule* module, bh_buffer* buff) {
+    i32 prev_len = buff->length;
+    bh_buffer_write_byte(buff, WASM_SECTION_ID_MEMORY);
+
+    bh_buffer vec_buff;
+    bh_buffer_init(&vec_buff, buff->allocator, 128);
+
+    i32 leb_len;
+    u8* leb = uint_to_uleb128((u64) 1, &leb_len);
+    bh_buffer_append(&vec_buff, leb, leb_len);
+
+    output_limits(4, 20, &vec_buff);
+
+    leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
+    bh_buffer_append(buff, leb, leb_len);
+
+    bh_buffer_concat(buff, vec_buff);
+    bh_buffer_free(&vec_buff);
+
+    return buff->length - prev_len;
+}
+
 static i32 output_globalsection(OnyxWasmModule* module, bh_buffer* buff) {
     i32 prev_len = buff->length;
     bh_buffer_write_byte(buff, WASM_SECTION_ID_GLOBAL);
@@ -1317,6 +1408,35 @@ static void output_instruction(WasmInstruction* instr, bh_buffer* buff) {
             bh_buffer_append(buff, leb, leb_len);
             break;
 
+        case WI_I32_STORE:
+        case WI_I32_STORE_8:
+        case WI_I32_STORE_16:
+        case WI_I64_STORE:
+        case WI_I64_STORE_8:
+        case WI_I64_STORE_16:
+        case WI_I64_STORE_32:
+        case WI_F32_STORE:
+        case WI_F64_STORE:
+        case WI_I32_LOAD:
+        case WI_I32_LOAD_8_S:
+        case WI_I32_LOAD_8_U:
+        case WI_I32_LOAD_16_S:
+        case WI_I32_LOAD_16_U:
+        case WI_I64_LOAD:
+        case WI_I64_LOAD_8_S:
+        case WI_I64_LOAD_8_U:
+        case WI_I64_LOAD_16_S:
+        case WI_I64_LOAD_16_U:
+        case WI_I64_LOAD_32_S:
+        case WI_I64_LOAD_32_U:
+        case WI_F32_LOAD:
+        case WI_F64_LOAD:
+            leb = uint_to_uleb128((u64) instr->data.i1, &leb_len);
+            bh_buffer_append(buff, leb, leb_len);
+            leb = uint_to_uleb128((u64) instr->data.i2, &leb_len);
+            bh_buffer_append(buff, leb, leb_len);
+            break;
+
         case WI_I32_CONST:
             leb = int_to_leb128((i64) instr->data.i1, &leb_len);
             bh_buffer_append(buff, leb, leb_len);
@@ -1393,6 +1513,7 @@ void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file) {
     output_typesection(module, &master_buffer);
     output_importsection(module, &master_buffer);
     output_funcsection(module, &master_buffer);
+    output_memorysection(module, &master_buffer);
     output_globalsection(module, &master_buffer);
     output_exportsection(module, &master_buffer);
     output_startsection(module, &master_buffer);