Started basics of pointers to sized data
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 27 Jul 2020 03:50:23 +0000 (22:50 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 27 Jul 2020 03:50:23 +0000 (22:50 -0500)
docs/plan
include/onyxastnodes.h
onyx
progs/ez.onyx
progs/print_funcs.onyx
src/onyx.c
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxutils.c
src/onyxwasm.c

index aa24c32e9f867d8e5f0f73aa2bb8d87dc117125f..6c4426ba50c65398b7e675b3cd0ff1afdb8f45e7 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -121,6 +121,10 @@ HOW:
 
         [ ] Static pointers to sized data
 
+        [ ] 'using' parameters
+            - The following example will bring the members of the struct into the scope as field accesses
+              and allow for a more OO style programming, without diving into the crap that is OO
+
         [ ] Start work on evaluating compile time known values.
             - An expression marked COMPTIME will be reduced to its value in the parse tree.
 
index 785cda91fe0b3880dd488f7529e41f19416a1989..078a9803d68888b9fa414974d422b00dd0020398 100644 (file)
@@ -43,8 +43,10 @@ typedef struct AstEnumType AstEnumType;
 typedef struct AstEnumValue AstEnumValue;
 
 typedef struct AstBinding AstBinding;
+typedef struct AstMemRes AstMemRes;
 typedef struct AstIncludeFile AstIncludeFile;
 typedef struct AstUsePackage AstUsePackage;
+typedef struct AstAlias AstAlias;
 typedef struct AstGlobal AstGlobal;
 typedef struct AstFunction AstFunction;
 typedef struct AstOverloadedFunction AstOverloadedFunction;
@@ -66,6 +68,8 @@ typedef enum AstKind {
     Ast_Kind_Package,
     Ast_Kind_Include_File,
     Ast_Kind_Use_Package,
+    Ast_Kind_Alias,
+    Ast_Kind_Memres,
 
     Ast_Kind_Binding,
     Ast_Kind_Function,
@@ -329,13 +333,18 @@ struct AstEnumValue { AstTyped_base; AstNumLit* value; };
 
 // 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 AstIncludeFile   { AstNode_base; OnyxToken *filename; };
 struct AstUsePackage    {
     AstNode_base;
 
     AstPackage *package;
     OnyxToken *alias;
-    bh_arr(OnyxToken *) only;
+    bh_arr(AstAlias *) only;
+};
+struct AstAlias         {
+    AstNode_base;
+    OnyxToken *alias;
 };
 struct AstGlobal        {
     AstTyped_base;
@@ -390,6 +399,7 @@ typedef enum EntityType {
     Entity_Type_String_Literal,
     Entity_Type_Enum,
     Entity_Type_Struct,
+    Entity_Type_Memory_Reservation,
     Entity_Type_Function_Header,
     Entity_Type_Global_Header,
     Entity_Type_Expression,
@@ -411,6 +421,7 @@ typedef struct Entity {
         AstStrLit             *strlit;
         AstStructType         *struct_type;
         AstEnumType           *enum_type;
+        AstMemRes             *mem_res;
     };
 } Entity;
 
diff --git a/onyx b/onyx
index 90f0812b9b7061f6d372896caefc770bb6f4d174..137784d6fac9b4ca65296c327bf433dc8fa87ee4 100755 (executable)
Binary files a/onyx and b/onyx differ
index 0ab71b5f6fd50e750c6d33e6b8802431e4f532cd..58d61414bc9092d0d7b7fd4fa534714995dadca0 100644 (file)
@@ -1,6 +1,10 @@
 use "progs/print_funcs"
 
-use package printing
+use package printing {
+    print, PrintableArray,
+    print_f32 as pf32,
+    print_buf
+}
 
 Foo :: struct {
     x : i32;
@@ -17,13 +21,35 @@ asdf :: proc (pa: PrintableArray) {
     for i: 0, pa.len print(pa.data[i] as i32);
 }
 
-SomeType :: enum #flags { Value1; Value2; Value3; Value4; }
+SomeType :: enum {
+    Value1;
+    Value2;
+    Value3;
+    Value4;
+}
 
 print_st :: proc (st: SomeType) {
     print(st as i32);
 }
 
+single_int : u8
+
+array : [N] Foo
+N :: 1024
+
 proc #export "main" {
+    print("Hello World! this is slightly longer\n");
+
+    print(__heap_start as i32);
+
+    print(print_buf as i32);
+
+    single_int = 10 as u8;
+    print(single_int as i32);
+
+    array[4].y = 1234;
+    print(array[4].y);
+
     st := SomeType.Value4;
     print_st(st);
 
@@ -43,6 +69,6 @@ proc #export "main" {
 
     print(1234);
 
-    print_f32(123.0f);
+    pf32(123.0f);
 }
 
index 3f48aab3d9c7008511d4405e5964d42f7d57db81..dd09204044f75b39197bd5d57983690948b24a22 100644 (file)
@@ -1,5 +1,9 @@
 package printing
 
+use package main {
+    N as buf_size
+}
+
 print_bool :: proc #foreign "host" "print" (value: bool) ---
 print_i32  :: proc #foreign "host" "print" (value: i32) ---
 print_f32  :: proc #foreign "host" "print" (value: f32) ---
@@ -55,3 +59,5 @@ print :: proc #overloaded {
     print_str,
     print_str_len,
 }
+
+print_buf : [buf_size] u8
\ No newline at end of file
index 76d1a3bc7cbb509288c1dfea2b2039b32f630da2..4da00e579170cb1a7678ade5136c23795a49473e 100644 (file)
@@ -244,6 +244,13 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res
                 break;
             }
 
+            case Ast_Kind_Memres: {
+                ent.type = Entity_Type_Memory_Reservation;
+                ent.mem_res = (AstMemRes *) node;
+                bh_arr_push(compiler_state->prog_info.entities, ent);
+                break;
+            }
+
             default: {
                 ent.type = Entity_Type_Expression;
                 ent.expr = (AstTyped *) node;
index eb943630614286bf2e635b3c3c5a62be83d448f6..232e498441a54f96fd48a4af435d970a6ff16920 100644 (file)
@@ -657,6 +657,8 @@ CHECK(expression, AstTyped** pexpr) {
         case Ast_Kind_Overloaded_Function: break;
         case Ast_Kind_Enum_Value: break;
 
+        case Ast_Kind_Memres: break;
+
         default:
             retval = 1;
             DEBUG_HERE;
@@ -952,6 +954,8 @@ void onyx_type_check() {
 
             case Entity_Type_Use_Package: break;
 
+            case Entity_Type_Memory_Reservation: break;
+
             default: DEBUG_HERE; break;
         }
     }
index 9c54464d3a8f06fe4efe26d74830c1cdc72b7c76..865efd392f8e024cd5be12400ebdf70caa63f47b 100644 (file)
@@ -1180,9 +1180,17 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
                     bh_arr_new(global_heap_allocator, upack->only, 4);
 
                     while (parser->curr->type != '}') {
-                        OnyxToken* only_token = expect_token(parser, Token_Type_Symbol);
+                        AstAlias* alias = make_node(AstAlias, Ast_Kind_Alias);
+                        alias->token = expect_token(parser, Token_Type_Symbol);
 
-                        bh_arr_push(upack->only, only_token);
+                        if (parser->curr->type == Token_Type_Keyword_Cast) {
+                            consume_token(parser);
+                            alias->alias = expect_token(parser, Token_Type_Symbol);
+                        } else {
+                            alias->alias = alias->token;
+                        }
+
+                        bh_arr_push(upack->only, alias);
 
                         if (parser->curr->type != '}')
                             expect_token(parser, ',');
@@ -1212,39 +1220,61 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
             consume_token(parser);
 
             expect_token(parser, ':');
-            expect_token(parser, ':');
 
-            AstTyped* node = parse_top_level_expression(parser);
+            if (parser->curr->type == ':') {
+                expect_token(parser, ':');
+
+                AstTyped* node = parse_top_level_expression(parser);
 
-            if (node->kind == Ast_Kind_Function) {
-                AstFunction* func = (AstFunction *) node;
+                if (node->kind == Ast_Kind_Function) {
+                    AstFunction* func = (AstFunction *) node;
 
-                if (func->exported_name == NULL)
-                    func->exported_name = symbol;
+                    if (func->exported_name == NULL)
+                        func->exported_name = symbol;
 
-            } else if (node->kind == Ast_Kind_Global) {
-                AstGlobal* global = (AstGlobal *) node;
+                } else if (node->kind == Ast_Kind_Global) {
+                    AstGlobal* global = (AstGlobal *) node;
 
-                if (global->exported_name == NULL)
-                    global->exported_name = symbol;
+                    if (global->exported_name == NULL)
+                        global->exported_name = symbol;
 
-            } else if (node->kind != Ast_Kind_Overloaded_Function
-                    && node->kind != Ast_Kind_StrLit) {
+                } else if (node->kind != Ast_Kind_Overloaded_Function
+                        && node->kind != Ast_Kind_StrLit) {
 
-                if (node->kind == Ast_Kind_Struct_Type || node->kind == Ast_Kind_Enum_Type) {
-                    ((AstStructType *)node)->name = bh_aprintf(global_heap_allocator,
-                        "%b", symbol->text, symbol->length);
+                    if (node->kind == Ast_Kind_Struct_Type || node->kind == Ast_Kind_Enum_Type) {
+                        ((AstStructType *)node)->name = bh_aprintf(global_heap_allocator,
+                            "%b", symbol->text, symbol->length);
+                    }
+
+                    // HACK
+                    add_node_to_process(parser, (AstNode *) node);
                 }
 
-                // HACK
-                add_node_to_process(parser, (AstNode *) node);
-            }
+                AstBinding* binding = make_node(AstBinding, Ast_Kind_Binding);
+                binding->token = symbol;
+                binding->node = (AstNode *) node;
 
-            AstBinding* binding = make_node(AstBinding, Ast_Kind_Binding);
-            binding->token = symbol;
-            binding->node = (AstNode *) node;
+                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);
 
-            return (AstNode *) binding;
+                add_node_to_process(parser, (AstNode *) memres);
+
+                AstBinding* binding = make_node(AstBinding, Ast_Kind_Binding);
+                binding->token = symbol;
+                binding->node = (AstNode *) memres;
+
+                return (AstNode *) binding;
+            }
         }
 
         default: break;
index 029a062b6980b385cdb2f473935a5016c34017cb..7c0bbccd77ed913d3e98a2377d1c7fd647d88b2b 100644 (file)
@@ -63,6 +63,7 @@ static void symres_global(AstGlobal* global);
 static void symres_overloaded_function(AstOverloadedFunction* ofunc);
 static void symres_use_package(AstUsePackage* package);
 static void symres_enum(AstEnumType* enum_node);
+static void symres_memres(AstMemRes** memres);
 
 static void scope_enter(Scope* new_scope) {
     if (new_scope->parent == NULL)
@@ -395,16 +396,16 @@ static void symres_use_package(AstUsePackage* package) {
     }
 
     if (package->only != NULL) {
-        bh_arr_each(OnyxToken *, tkn, package->only) {
+        bh_arr_each(AstAlias *, alias, package->only) {
 
-            AstNode* thing = symbol_resolve(p->scope, *tkn);
+            AstNode* thing = symbol_resolve(p->scope, (*alias)->token);
             if (thing == NULL) {
                 onyx_message_add(Msg_Type_Literal,
-                    (*tkn)->pos,
+                    (*alias)->token->pos,
                     "not found in package");
                 return;
             }
-            symbol_introduce(semstate.curr_package->scope, *tkn, thing);
+            symbol_introduce(semstate.curr_package->scope, (*alias)->alias, thing);
         }
     }
 
@@ -454,6 +455,29 @@ static void symres_enum(AstEnumType* enum_node) {
     }
 }
 
+static void symres_memres(AstMemRes** memres) {
+    (*memres)->type_node = symres_type((*memres)->type_node);
+    (*memres)->type = type_build_from_ast(semstate.allocator, (*memres)->type_node);
+
+    if ((*memres)->type->kind != Type_Kind_Array) {
+        Type* ptr_type = type_make_pointer(semstate.allocator, (*memres)->type);
+        (*memres)->type = ptr_type;
+
+        AstMemRes* new_memres = onyx_ast_node_new(semstate.node_allocator, sizeof(AstMemRes), Ast_Kind_Memres);
+        memcpy(new_memres, (*memres), sizeof(AstMemRes));
+
+        // BIG HACK: converting the (*memres) node to a dereference node to not break
+        // already resolved symbols
+        ((AstDereference *) (*memres))->kind = Ast_Kind_Dereference;
+        ((AstDereference *) (*memres))->type_node = (*memres)->type_node;
+        ((AstDereference *) (*memres))->type = (*memres)->type->Pointer.elem;
+        ((AstDereference *) (*memres))->expr = (AstTyped *) new_memres;
+
+        // BUT retain the 'old' memres in the entity list
+        *memres = new_memres;
+    }
+}
+
 void onyx_resolve_symbols() {
 
     semstate.curr_scope = semstate.program->global_scope;
@@ -477,6 +501,7 @@ void onyx_resolve_symbols() {
             case Entity_Type_Expression:          symres_expression(&entity->expr); break;
             case Entity_Type_Struct:              symres_type((AstType *) entity->struct_type); break;
             case Entity_Type_Enum:                symres_enum(entity->enum_type); break;
+            case Entity_Type_Memory_Reservation:  symres_memres(&entity->mem_res); break;
 
             default: break;
         }
index 8c53165b9b2828c93c35b24b495d7450b6138b65..ed3bd9da4e3172d6d81d3668f6e5751c856b8850 100644 (file)
@@ -14,6 +14,7 @@ static const char* ast_node_names[] = {
     "PACKAGE",
     "PROGRAM",
     "USE",
+    "ALIAS",
 
     "BINDING",
     "FUNCTION",
index 1a0f5e98e1a23b2baae5b2947025a7ab81a3acab..aa03c2d7b9c30de052c4d1b80cb3ba51a67fb8f8 100644 (file)
@@ -992,6 +992,12 @@ COMPILE_FUNC(expression, AstTyped* expr) {
             break;
         }
 
+        case Ast_Kind_Memres: {
+            AstMemRes* memres = (AstMemRes *) expr;
+            WID(WI_I32_CONST, memres->addr);
+            break;
+        }
+
         default:
             bh_printf("Unhandled case: %d\n", expr->kind);
             DEBUG_HERE;
@@ -1343,6 +1349,30 @@ static void compile_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) {
     bh_arr_push(mod->data, datum);
 }
 
+static void compile_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) {
+    u64 alignment = type_alignment_of(memres->type);
+    u64 size = type_size_of(memres->type);
+
+    u32 offset = mod->next_datum_offset;
+    if (offset % alignment != 0) {
+        offset += alignment - (offset % alignment);
+    }
+
+    ptr data = bh_alloc_array(global_heap_allocator, i8, size);
+    memset(data, 0, size);
+
+    WasmDatum datum = {
+        .offset = offset,
+        .length = size,
+        .data = data
+    };
+
+    memres->addr = offset;
+    mod->next_datum_offset = offset + size;
+
+    bh_arr_push(mod->data, datum);
+}
+
 OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {
     OnyxWasmModule module = {
         .allocator = alloc,
@@ -1438,6 +1468,18 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) {
                 break;
             }
 
+            case Entity_Type_Memory_Reservation: {
+                compile_memory_reservation(module, (AstMemRes *) entity->mem_res);
+                
+                // HACK: To put this here
+                // NOTE: Round up to the nearest multiple of 16
+                builtin_heap_start.value.i =
+                    (module->next_datum_offset & 15)
+                    ? ((module->next_datum_offset >> 4) + 1) << 4
+                    : module->next_datum_offset;
+                break;
+            }
+
             case Entity_Type_Function: compile_function(module, entity->function); break;
             case Entity_Type_Global:   compile_global(module,   entity->global); break;