changed: foreign directives no longer require string literals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 2 Apr 2023 21:46:43 +0000 (16:46 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 2 Apr 2023 21:46:43 +0000 (16:46 -0500)
compiler/include/astnodes.h
compiler/src/astnodes.c
compiler/src/checker.c
compiler/src/parser.c
compiler/src/symres.c
compiler/src/wasm_emit.c
compiler/src/wasm_type_table.h
tests/aoc-2021/day04.onyx

index c9fd21af7c2f2654ce28021c2d9770b38fc42923..ab95741dbbc5f4cba280d532ea59f1bb0ab0e112 100644 (file)
@@ -583,6 +583,11 @@ struct Arguments {
     i32 used_argument_count;
 };
 
+typedef struct ForeignReference {
+    AstTyped *module_name;
+    AstTyped *import_name;
+} ForeignReference;
+
 
 // Base Nodes
 #define AstNode_base \
@@ -1064,8 +1069,7 @@ struct AstGlobal        {
 
     char* name;
 
-    OnyxToken* foreign_module;
-    OnyxToken* foreign_name;
+    ForeignReference foreign;
 };
 struct AstParam {
     // HACK CLEANUP: This does not need to have a local buried inside of it.
@@ -1294,11 +1298,7 @@ struct AstFunction {
     union {
         OnyxToken* intrinsic_name;
 
-        // NOTE: Used when the function is declared as foreign
-        struct {
-            OnyxToken* foreign_module;
-            OnyxToken* foreign_name;
-        };
+        ForeignReference foreign;
     };
 
     struct Entity* entity_header;
@@ -1455,7 +1455,7 @@ struct AstForeignBlock {
     AstTyped_base;
 
     Scope* scope;
-    OnyxToken *module_name;
+    AstTyped *module_name;
     bh_arr(struct Entity *) captured_entities;
 
     u32 foreign_block_number;
@@ -1844,6 +1844,7 @@ AstNumLit*        make_bool_literal(bh_allocator, b32 b);
 AstNumLit*        make_int_literal(bh_allocator a, i64 value);
 AstNumLit*        make_float_literal(bh_allocator a, f64 value);
 AstRangeLiteral*  make_range_literal(bh_allocator a, AstTyped* low, AstTyped* high);
+AstStrLit*        make_string_literal(bh_allocator a, OnyxToken *token);
 AstBinaryOp*      make_binary_op(bh_allocator a, BinaryOp operation, AstTyped* left, AstTyped* right);
 AstArgument*      make_argument(bh_allocator a, AstTyped* value);
 AstFieldAccess*   make_field_access(bh_allocator a, AstTyped* node, char* field);
index 3227cab7784fe194b932fea6965e0a225e955932..cfab106ce1877e29fa4108500ac3c7d3413d414a 100644 (file)
@@ -1488,6 +1488,14 @@ AstRangeLiteral* make_range_literal(bh_allocator a, AstTyped* low, AstTyped* hig
     return rl;
 }
 
+AstStrLit* make_string_literal(bh_allocator a, OnyxToken *token) {
+    AstStrLit *str = onyx_ast_node_new(a, sizeof(AstStrLit), Ast_Kind_StrLit);
+    str->flags |= Ast_Flag_Comptime;
+    str->type_node = builtin_string_type;
+    str->token = token;
+    return str;
+}
+
 AstBinaryOp* make_binary_op(bh_allocator a, BinaryOp operation, AstTyped* left, AstTyped* right) {
     AstBinaryOp* binop_node = onyx_ast_node_new(a, sizeof(AstBinaryOp), Ast_Kind_Binary_Op);
     binop_node->left  = left;
index 01b56267dcad39693907d1cd2c416d62a194bf40..be9c4f2cfaac6b44e3d300de193091f75d3f001a 100644 (file)
@@ -2924,6 +2924,11 @@ CheckStatus check_function_header(AstFunction* func) {
     func->type = type_build_function_type(context.ast_alloc, func);
     if (func->type == NULL) YIELD(func->token->pos, "Waiting for function type to be constructed");
 
+    if (func->foreign.import_name) { 
+        CHECK(expression, &func->foreign.module_name);
+        CHECK(expression, &func->foreign.import_name);
+    }
+
     return Check_Success;
 }
 
index 17ae7a42bb3b6d941ebb47e411e2d5de6101fbbe..1d06f1ab61981eb98f164e82f9de8556c384d9af 100644 (file)
@@ -2615,8 +2615,8 @@ static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* tok
         }
 
         else if (parse_possible_directive(parser, "foreign")) {
-            func_def->foreign_module = expect_token(parser, Token_Type_Literal_String);
-            func_def->foreign_name   = expect_token(parser, Token_Type_Literal_String);
+            func_def->foreign.module_name = parse_expression(parser, 0);
+            func_def->foreign.import_name = parse_expression(parser, 0);
 
             func_def->is_foreign = 1;
         }
@@ -3040,7 +3040,7 @@ static AstForeignBlock* parse_foreign_block(OnyxParser* parser, OnyxToken *token
         fb->uses_dyncall = 1;
     }
 
-    fb->module_name = expect_token(parser, Token_Type_Literal_String);
+    fb->module_name = parse_expression(parser, 0);
 
     //
     // This has a fun implication that there cannot be foreign blocks in the builtin
index d6600aacaaad94a9050d2c89e0e74e08f74782b9..f56d4a5016f69d282bb3a71604fd8eabc11f7ced 100644 (file)
@@ -1017,6 +1017,11 @@ SymresStatus symres_function_header(AstFunction* func) {
         SYMRES(expression, (AstTyped **) &func->deprecated_warning);
     }
 
+    if (func->foreign.import_name) {
+        SYMRES(expression, &func->foreign.module_name);
+        SYMRES(expression, &func->foreign.import_name);
+    }
+
     scope_leave();
 
     return Symres_Success;
@@ -1592,6 +1597,13 @@ static SymresStatus symres_foreign_block(AstForeignBlock *fb) {
     if (fb->scope == NULL)
         fb->scope = scope_create(context.ast_alloc, current_scope, fb->token->pos);
 
+    SYMRES(expression, &fb->module_name);
+
+    if (fb->module_name->kind != Ast_Kind_StrLit) {
+        onyx_report_error(fb->token->pos, Error_Critical, "Expected module name to be a compile-time string literal.");
+        return Symres_Error;
+    }
+
     bh_arr_each(Entity *, pent, fb->captured_entities) {
         Entity *ent = *pent;
         if (ent->type == Entity_Type_Function_Header) {
@@ -1600,8 +1612,8 @@ static SymresStatus symres_foreign_block(AstForeignBlock *fb) {
                 return Symres_Error;
             }
 
-            ent->function->foreign_name = ent->function->intrinsic_name; // Hmm... This might not be right?
-            ent->function->foreign_module = fb->module_name;
+            ent->function->foreign.import_name = make_string_literal(context.ast_alloc, ent->function->intrinsic_name);
+            ent->function->foreign.module_name = fb->module_name;
             ent->function->is_foreign = 1;
             ent->function->is_foreign_dyncall = fb->uses_dyncall;
             ent->function->entity = NULL;
index 2c377c02d1e7e8bffe3f1d1723014479732f7007..7595168e7540d40180504bb4f5a9883f2617b846 100644 (file)
@@ -4160,9 +4160,11 @@ static void emit_foreign_function(OnyxWasmModule* mod, AstFunction* fd) {
     i32 type_idx = generate_type_idx(mod, fd->type);
 
     char *module, *name;
+    OnyxToken *foreign_module = fd->foreign.module_name->token;
+    OnyxToken *foreign_import = fd->foreign.import_name->token;
 
     if (fd->is_foreign_dyncall) {
-        module = bh_aprintf(global_heap_allocator, "dyncall:%b", fd->foreign_module->text, fd->foreign_module->length);
+        module = bh_aprintf(global_heap_allocator, "dyncall:%b", foreign_module->text, foreign_module->length);
 
         char type_encoding[65] = {0};
         encode_type_as_dyncall_symbol(type_encoding, fd->type->Function.return_type);
@@ -4171,11 +4173,11 @@ static void emit_foreign_function(OnyxWasmModule* mod, AstFunction* fd) {
             encode_type_as_dyncall_symbol(type_encoding, param->local->type);
         }
 
-        name = bh_aprintf(global_heap_allocator, "%b:%s", fd->foreign_name->text, fd->foreign_name->length, type_encoding);
+        name = bh_aprintf(global_heap_allocator, "%b:%s", foreign_import->text, foreign_import->length, type_encoding);
 
     } else {
-        module = bh_aprintf(global_heap_allocator, "%b", fd->foreign_module->text, fd->foreign_module->length);
-        name = bh_aprintf(global_heap_allocator, "%b", fd->foreign_name->text, fd->foreign_name->length);
+        module = bh_aprintf(global_heap_allocator, "%b", foreign_module->text, foreign_module->length);
+        name = bh_aprintf(global_heap_allocator, "%b", foreign_import->text, foreign_import->length);
     }
 
     WasmImport import = {
index fc620bce43ef2c4a48028f3b17843bc51c9c2e0d..33f4c5b870e01f08512040c405d8311d90bc9907 100644 (file)
@@ -662,9 +662,10 @@ static u64 build_foreign_blocks(OnyxWasmModule* module) {
             AstFunction *func = (AstFunction *) fb->scope->symbols[i].value;
             if (func->kind != Ast_Kind_Function) continue;
 
+            OnyxToken *import_name = func->foreign.import_name->token;
             u32 func_name_base = foreign_buffer.length;
-            u32 func_name_length = func->foreign_name->length;
-            bh_buffer_append(&foreign_buffer, func->foreign_name->text, func_name_length);
+            u32 func_name_length = import_name->length;
+            bh_buffer_append(&foreign_buffer, import_name->text, func_name_length);
 
             name_offsets[funcs_length] = func_name_base;
             name_lengths[funcs_length] = func_name_length;
@@ -681,9 +682,10 @@ static u64 build_foreign_blocks(OnyxWasmModule* module) {
             bh_buffer_write_u32(&foreign_buffer, func_types[i]);
         }
 
+        OnyxToken *module_name = fb->module_name->token;
         u32 name_base = foreign_buffer.length;
-        u32 name_length = fb->module_name->length;
-        bh_buffer_append(&foreign_buffer, fb->module_name->text, name_length);
+        u32 name_length = module_name->length;
+        bh_buffer_append(&foreign_buffer, module_name->text, name_length);
         bh_buffer_align(&foreign_buffer, 8);
 
         foreign_info[index] = foreign_buffer.length;
index f63e2ab84c08d6adee305dd1be3a6bdc7f0cbecd..9566b3ef75c443bbd76cad124f2058ed1687f0c9 100644 (file)
@@ -1,5 +1,3 @@
-#load "core/std"
-
 use core {*}
 
 Cell :: u8
@@ -29,8 +27,7 @@ main :: (args) => {
 
         boards: [..] Board;
         while !io.reader_empty(&reader) {
-            array.insert_empty(&boards, boards.count);
-            board := &boards[boards.count - 1];
+            board := array.alloc_one(&boards);
             board.has_won = false;
             memory.set(&board.marked, 0, sizeof typeof board.marked);