added memory reservation initial values
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Aug 2020 17:43:49 +0000 (12:43 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Aug 2020 17:43:49 +0000 (12:43 -0500)
docs/plan
include/onyxastnodes.h
include/onyxtypes.h
onyx
progs/stack_based.onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxwasm.c

index 6ef779a791c9da80c508f5b9dbd027b40868e1cc..838906d84761e81874f9709ed895e59bf5267340 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -161,6 +161,13 @@ HOW:
 
         [ ] Array literals
 
+        [ ] Struct literals
+
+        [ ] Top level variable initialization
+            - Works for numeric literals
+
+        [ ] 'use' enums and packages at an arbitrary scope
+
         [ ] Better checking for casts
             - Checking which things are allowed to cast to/from should be checked in the checker,
                 not in the wasm generatation
index 6e9401f6aa7d66b7cd8f16ea6e669442509de4f7..6d242e734f8513974bcf95c7790dde369a3586fe 100644 (file)
@@ -350,7 +350,7 @@ struct AstTypeAlias { AstType_base; AstType* to; };
 
 // Top level nodes
 struct AstBinding       { AstTyped_base; AstNode* node; };
-struct AstMemRes        { AstTyped_base; u64 addr; };           // HACK: This has to be the same size as AstDereference
+struct AstMemRes        { AstTyped_base; u64 addr; AstTyped *initial_value; }; // HACK: This has to be the same size or bigger as AstDereference
 struct AstIncludeFile   { AstNode_base; OnyxToken *filename; };
 struct AstUsePackage    {
     AstNode_base;
index fb2fa7e9a8258cd3200505ae4a4160f9e3d5e97c..7d17297cb7103addf55c12081cc89e4df80c9485 100644 (file)
@@ -125,6 +125,7 @@ b32 type_is_struct(Type* type);
 b32 type_is_bool(Type* type);
 b32 type_is_integer(Type* type);
 b32 type_is_numeric(Type* type);
+b32 type_is_compound(Type* type);
 b32 type_results_in_void(Type* type);
 
 #endif // #ifndef ONYX_TYPES
diff --git a/onyx b/onyx
index bedfe214813a519434ac328dfe9a62dbed941910..144ca80f6ff59a5c1a8701aa17d71c0bb1957dc2 100755 (executable)
Binary files a/onyx and b/onyx differ
index d3a048c1e7e07d719fe373ff707689ce83a81a6c..5483f7c90af96e70985f3c50828fd37cb1e7c621 100644 (file)
@@ -44,9 +44,12 @@ vec_add :: proc (v: Vec3, u: Vec3, use out: ^Vec3) {
     z = v.z + u.z;
 }
 
+some_value := #char "A";
+
 start :: proc #export {
     heap_init();
     print("Hello, World!");
+    print_hex(cast(u64) some_value);
     print("Hello, World!");
     print_ptr(__heap_start);
     print_ptr(__stack_base);
@@ -54,9 +57,7 @@ start :: proc #export {
     print_bin(42l);
     print_hex(42l);
 
-    for i: #char "a", #char "f" {
-        print_hex(cast(u64) i);
-    }
+    for i: #char "a", #char "f" do print_hex(cast(u64) i);
 
     a := 12345;
 
index 3fb2967e182eecc909bf9de46c09436284c91245..1a32875cce1a2895987cb7b195e30cd43b4a76b5 100644 (file)
@@ -26,6 +26,7 @@ CHECK(function, AstFunction* func);
 CHECK(overloaded_function, AstOverloadedFunction* func);
 CHECK(struct, AstStructType* s_node);
 CHECK(function_header, AstFunction* func);
+CHECK(memres, AstMemRes* memres);
 
 static inline void fill_in_type(AstTyped* node) {
     if (node->type == NULL)
@@ -1071,6 +1072,27 @@ CHECK(function_header, AstFunction* func) {
     return 0;
 }
 
+CHECK(memres, AstMemRes* memres) {
+    fill_in_type((AstTyped *) memres);
+
+    if (memres->initial_value != NULL) {
+        fill_in_type(memres->initial_value);
+
+        Type* memres_type = memres->type;
+        if (!type_is_compound(memres_type)) memres_type = memres_type->Pointer.elem;
+
+        if (!types_are_compatible(memres_type, memres->initial_value->type)) {
+            onyx_message_add(Msg_Type_Binop_Mismatch,
+                    memres->token->pos,
+                    type_get_name(memres_type),
+                    type_get_name(memres->initial_value->type));
+            return 1;
+        }
+    }
+    
+    return 0;
+}
+
 CHECK(node, AstNode* node) {
     switch (node->kind) {
         case Ast_Kind_Function:             return check_function((AstFunction *) node);
@@ -1119,6 +1141,10 @@ void onyx_type_check() {
                     if (check_struct((AstStructType *) entity->type_alias)) return;
                 break;
 
+            case Entity_Type_Memory_Reservation:
+                if (check_memres(entity->mem_res)) return;
+                break;
+
             case Entity_Type_Enum: break;
 
             case Entity_Type_String_Literal: break;
@@ -1129,8 +1155,6 @@ void onyx_type_check() {
 
             case Entity_Type_Use_Package: break;
 
-            case Entity_Type_Memory_Reservation: break;
-
             default: DEBUG_HERE; break;
         }
     }
index 8849e451510b84265f1c139012ea054917d54316..6cab751545c3565f2cdf3f356e5c41675577ea98 100644 (file)
@@ -169,10 +169,6 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             negate_node->operation = Unary_Op_Negate;
             negate_node->expr = factor;
 
-            if ((factor->flags & Ast_Flag_Comptime) != 0) {
-                negate_node->flags |= Ast_Flag_Comptime;
-            }
-
             retval = (AstTyped *) negate_node;
             break;
         }
@@ -183,10 +179,6 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             not_node->token = expect_token(parser, '!');
             not_node->expr = parse_factor(parser);
 
-            if ((not_node->expr->flags & Ast_Flag_Comptime) != 0) {
-                not_node->flags |= Ast_Flag_Comptime;
-            }
-
             retval = (AstTyped *) not_node;
             break;
         }
@@ -572,10 +564,6 @@ static AstTyped* parse_expression(OnyxParser* parser) {
 
             right = parse_factor(parser);
             bin_op->right = right;
-
-            if ((left->flags & Ast_Flag_Comptime) != 0 && (right->flags & Ast_Flag_Comptime) != 0) {
-                bin_op->flags |= Ast_Flag_Comptime;
-            }
         }
     }
 
@@ -1460,16 +1448,21 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
 
                 return (AstNode *) binding;
             } else {
-                if (parser->curr->type == '=') {
-                    onyx_message_add(Msg_Type_Literal,
-                            parser->curr->pos,
-                            "assigning initial values to memory reservations isn't allowed yet.");
-                    break;
-                }
-
                 AstMemRes* memres = make_node(AstMemRes, Ast_Kind_Memres);
                 memres->token = symbol;
-                memres->type_node = parse_type(parser);
+
+                if (parser->curr->type == '=') {
+                    consume_token(parser);
+                    memres->initial_value = parse_expression(parser);
+
+                } else {
+                    memres->type_node = parse_type(parser);
+
+                    if (parser->curr->type == '=') {
+                        consume_token(parser);
+                        memres->initial_value = parse_expression(parser);
+                    }
+                }
 
                 if (is_private)
                     memres->flags |= Ast_Flag_Private_Package;
index 116eb15895d8088cf4adbb60cb7dd48f3c64cbfa..8a095b04400ffed6ecf0328517168749444fa80f 100644 (file)
@@ -495,11 +495,26 @@ static void symres_enum(AstEnumType* enum_node) {
 
 static void symres_memres(AstMemRes** memres) {
     (*memres)->type_node = symres_type((*memres)->type_node);
-    if ((*memres)->type_node == NULL) return;
+    if ((*memres)->initial_value != NULL) {
+        symres_expression(&(*memres)->initial_value);
+
+        if (((*memres)->initial_value->flags & Ast_Flag_Comptime) == 0) {
+            onyx_message_add(Msg_Type_Literal,
+                    (*memres)->initial_value->token->pos,
+                    "top level expressions must be compile time known");
+            return;
+        }
+
+        if ((*memres)->type_node == NULL)
+            (*memres)->type_node = (*memres)->initial_value->type_node;
+
+    } else {
+        if ((*memres)->type_node == NULL) return;
+    }
 
     (*memres)->type = type_build_from_ast(semstate.allocator, (*memres)->type_node);
 
-    if ((*memres)->type->kind != Type_Kind_Array && (*memres)->type->kind != Type_Kind_Struct) {
+    if (!type_is_compound((*memres)->type)) {
         Type* ptr_type = type_make_pointer(semstate.allocator, (*memres)->type);
         (*memres)->type = ptr_type;
 
index df03d67764c5574872938e7481c23cac12601cae..b61e05fd4b698d711283a155fbb9350327454253 100644 (file)
@@ -483,6 +483,11 @@ b32 type_is_numeric(Type* type) {
     return type->Basic.kind >= Basic_Kind_I8 && type->Basic.kind <= Basic_Kind_F64;
 }
 
+b32 type_is_compound(Type* type) {
+    return type->kind == Type_Kind_Array
+        || type->kind == Type_Kind_Struct;
+}
+
 b32 type_results_in_void(Type* type) {
     return (type == NULL)
         || (type->kind == Type_Kind_Basic && type->Basic.kind == Basic_Kind_Void)
index dc821569aa45a4967bbb4110f99021561f461c6a..665cd82f34bd7bbd7c6cdd5ba50ac8ef20904007 100644 (file)
@@ -1645,25 +1645,72 @@ static void compile_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) {
     bh_arr_push(mod->data, datum);
 }
 
+static void compile_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) {
+    switch (node->kind) {
+    case Ast_Kind_NumLit: {
+        switch (node->type->Basic.kind) {
+        case Basic_Kind_Bool:
+        case Basic_Kind_I8:
+        case Basic_Kind_U8:
+        case Basic_Kind_I16:
+        case Basic_Kind_U16:
+        case Basic_Kind_I32:
+        case Basic_Kind_U32:
+        case Basic_Kind_Rawptr:
+            *((i32 *) data) = ((AstNumLit *) node)->value.i;
+            return;
+
+        case Basic_Kind_I64:
+        case Basic_Kind_U64:
+            *((i64 *) data) = ((AstNumLit *) node)->value.l;
+            return;
+
+        case Basic_Kind_F32:
+            *((f32 *) data) = ((AstNumLit *) node)->value.f;
+            return;
+
+        case Basic_Kind_F64:
+            *((f64 *) data) = ((AstNumLit *) node)->value.d;
+            return;
+
+        default: break;
+        }
+
+        //fallthrough
+    }
+    default: onyx_message_add(Msg_Type_Literal,
+            node->token->pos,
+            "invalid data");
+    }
+}
+
 static void compile_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) {
-    u64 alignment = type_alignment_of(memres->type);
-    u64 size = type_size_of(memres->type);
+    Type* effective_type = memres->type;
+    if (!type_is_compound(effective_type)) effective_type = effective_type->Pointer.elem;
+
+    u64 alignment = type_alignment_of(effective_type);
+    u64 size = type_size_of(effective_type);
 
     u32 offset = mod->next_datum_offset;
     if (offset % alignment != 0) {
         offset += alignment - (offset % alignment);
     }
 
-    // WasmDatum datum = {
-    //     .offset = offset,
-    //     .length = size,
-    //     .data = NULL
-    // };
+    if (memres->initial_value != NULL) {
+        u8* data = bh_alloc(mod->allocator, size);
+        compile_raw_data(mod, data, memres->initial_value);
+
+        WasmDatum datum = {
+            .offset = offset,
+            .length = size,
+            .data = data,
+        };
+
+        bh_arr_push(mod->data, datum);
+    }
 
     memres->addr = offset;
     mod->next_datum_offset = offset + size;
-
-    // bh_arr_push(mod->data, datum);
 }
 
 static void compile_file_contents(OnyxWasmModule* mod, AstFileContents* fc) {