changed how #export works
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 28 Apr 2021 18:45:43 +0000 (13:45 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 28 Apr 2021 18:45:43 +0000 (13:45 -0500)
bin/onyx
core/runtime/js.onyx
core/runtime/wasi.onyx
include/onyxastnodes.h
progs/odin_example.onyx
src/onyxastnodes.c
src/onyxchecker.c
src/onyxentities.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index e3ce621b06b47a32363c062fa84399bb31ea68ec..9870c926db10c24c9168feef6b46e593171e7037 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index f109614fc8d2395771a5f92182b9f5ae40eb3f1f..17cc99bf79ad0652bbf2fd02d26e1700463a6a5b 100644 (file)
@@ -9,7 +9,7 @@ __exit          :: (status: i32) -> void #foreign "host" "exit" ---
 
 // The builtin _start proc.
 // Sets up everything needed for execution.
-_start :: () -> void #export "_start" {
+#export "_start" () {
     __runtime_initialize();
 
     args: [] cstr = .{ null, 0 };
index c6a2039962cb159314a36353751e5b4a05bcb166..a90ffabf0c6ae40e18c52e7263f572e27079ab14 100644 (file)
@@ -20,7 +20,7 @@ __exit :: (status: i32) do proc_exit(status);
 
 // The builtin _start proc.
 // Sets up everything needed for execution.
-_start :: () -> void #export "_start" {
+#export "_start" () {
     __runtime_initialize();
 
     args : [] cstr;
index 941f6a80bf2a18e53597ac320524e597c7ab548a..bd88b7fd3d783deb7954103b50cce882ce77ff69 100644 (file)
@@ -34,6 +34,7 @@
     NODE(DirectiveError)       \
     NODE(DirectiveAddOverload) \
     NODE(DirectiveOperator)    \
+    NODE(DirectiveExport)      \
                                \
     NODE(Return)               \
     NODE(Jump)                 \
@@ -177,6 +178,7 @@ typedef enum AstKind {
     Ast_Kind_Directive_Error,
     Ast_Kind_Directive_Add_Overload,
     Ast_Kind_Directive_Operator,
+    Ast_Kind_Directive_Export,
 
     Ast_Kind_Count
 } AstKind;
@@ -734,16 +736,8 @@ struct AstGlobal        {
 
     OnyxToken* name;
 
-    union {
-        // NOTE: Used when a global is exported with a specific name
-        OnyxToken* exported_name;
-
-        // NOTE: Used when the global is declared as foreign
-        struct {
-            OnyxToken* foreign_module;
-            OnyxToken* foreign_name;
-        };
-    };
+    OnyxToken* foreign_module;
+    OnyxToken* foreign_name;
 };
 struct AstParam {
     // HACK CLEANUP: This does not need to have a local buried inside of it.
@@ -771,9 +765,12 @@ struct AstFunction {
     // procedure call. Then it is set to the token of the call node.
     OnyxToken* generated_from;
 
+    // NOTE: This is NULL, unless this function is used in a "#export" directive.
+    // It is undefined which name it will have if there are multiple export directives
+    // for this particular function.
+    OnyxToken* exported_name;
+
     union {
-        // NOTE: Used when a function is exported with a specific name
-        OnyxToken* exported_name;
         OnyxToken* intrinsic_name;
 
         // NOTE: Used when the function is declared as foreign
@@ -910,6 +907,12 @@ struct AstDirectiveOperator {
     AstTyped *overload;
 };
 
+struct AstDirectiveExport {
+    AstNode_base;
+
+    OnyxToken* export_name;
+    AstTyped* export;
+};
 
 typedef enum EntityState {
     Entity_State_Error,
index 9a3074136e90d26285986d8b7d6435cdb45efbe4..ab16c27be34c8159fc312387f69e7e08be5af06c 100644 (file)
@@ -56,7 +56,7 @@ make_bar :: () -> Bar {
     return bar;
 }
 
-f :: () -> [5] [2] u32 #export "IAMTHEFUNCTION" {
+f :: () -> [5] [2] u32 {
     // This method of returning an array will leak memory, since this is never freed.
     // mem := cast(^u32) calloc(sizeof [5] [2] u32);
     // for i: 0 .. 10 do mem[i] = 1234 + i;
@@ -85,7 +85,7 @@ BadUnion :: struct {
 Vec2   :: struct { x: i32; y: i32; }
 Entity :: struct { use pos: Vec2; }
 
-array_literal_optim :: () -> void #export {
+array_literal_optim :: () -> void {
     bar : [5] u32;
     bar = u32.[ 1, 2, 3, 4, 5 ];
     bar[2] = 1234;
index 866f2620787a35a6831bd6cfe864b3873982d777..aa711518af55da4a0bb4555e7ce66412c3f00f6c 100644 (file)
@@ -83,6 +83,7 @@ static const char* ast_node_names[] = {
     "STATIC ERROR",
     "ADD OVERLOAD",
     "OPERATOR OVERLOAD",
+    "EXPORT",
 
     "AST_NODE_KIND_COUNT",
 };
index 00b8159e19e4251a0ddeb7018d2a4e866ebc521a..f9fa95dd44fc13edc4e7e47035ab003118a1be50 100644 (file)
@@ -1456,10 +1456,7 @@ CheckStatus check_global(AstGlobal* global) {
     fill_in_type((AstTyped *) global);
 
     if (global->type == NULL) {
-        onyx_report_error(global->token->pos,
-                "Unable to resolve type for global '%b'.",
-                global->exported_name->text,
-                global->exported_name->length);
+        onyx_report_error(global->token->pos, "Unable to resolve type for global.");
 
         return Check_Error;
     }
@@ -1709,6 +1706,8 @@ CheckStatus check_function_header(AstFunction* func) {
 
     func->type = type_build_function_type(context.ast_alloc, func);
 
+    /*
+    CLEANUP: These checks need to be ported to a process directive check.
     if ((func->flags & Ast_Flag_Exported) != 0) {
         if ((func->flags & Ast_Flag_Foreign) != 0) {
             onyx_report_error(func->token->pos, "exporting a foreign function");
@@ -1725,6 +1724,7 @@ CheckStatus check_function_header(AstFunction* func) {
             return Check_Error;
         }
     }
+    */
 
     return Check_Success;
 }
index 5a11f4d708e638e32e3bac6e1e1eb8d575a86857..c5b1972e7ee1d366a37ae3910b582b8932c6e86a 100644 (file)
@@ -303,6 +303,7 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s
             break;   
         }
 
+        case Ast_Kind_Directive_Export:
         case Ast_Kind_Directive_Add_Overload:
         case Ast_Kind_Directive_Operator: {
             ent.type = Entity_Type_Process_Directive;
index a9eb181ffbc0f03ae9bc52859c7246049cdd0d42..1f04cc8313d1fdfe9efd3dc3122e57ed65953093 100644 (file)
@@ -1904,14 +1904,6 @@ static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* tok
             func_def->flags |= Ast_Flag_Foreign;
         }
 
-        else if (parse_possible_directive(parser, "export")) {
-            func_def->flags |= Ast_Flag_Exported;
-
-            if (parser->curr->type == Token_Type_Literal_String) {
-                func_def->exported_name = expect_token(parser, Token_Type_Literal_String);
-            }
-        }
-
         // HACK: NullProcHack
         else if (parse_possible_directive(parser, "null")) {
             func_def->flags |= Ast_Flag_Proc_Is_Null;
@@ -1995,14 +1987,6 @@ static AstTyped* parse_global_declaration(OnyxParser* parser) {
             global_node->flags |= Ast_Flag_Foreign;
         }
 
-        else if (parse_possible_directive(parser, "export")) {
-            global_node->flags |= Ast_Flag_Exported;
-
-            if (parser->curr->type == Token_Type_Literal_String) {
-                global_node->exported_name = expect_token(parser, Token_Type_Literal_String);
-            }
-        }
-
         else {
             OnyxToken* directive_token = expect_token(parser, '#');
             OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
@@ -2137,25 +2121,22 @@ static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol
     if (node->kind == Ast_Kind_Function) {
         AstFunction* func = (AstFunction *) node;
 
-        if (func->exported_name == NULL)
-            func->exported_name = symbol;
+        if (func->intrinsic_name == NULL)
+            func->intrinsic_name = symbol;
 
         func->name = symbol;
 
     } else if (node->kind == Ast_Kind_Polymorphic_Proc) {
         AstPolyProc* proc = (AstPolyProc *) node;
 
-        if (proc->base_func->exported_name == NULL)
-            proc->base_func->exported_name = symbol;
+        if (proc->base_func->intrinsic_name == NULL)
+            proc->base_func->intrinsic_name = symbol;
 
         proc->base_func->name = symbol;
 
     } else if (node->kind == Ast_Kind_Global) {
         AstGlobal* global = (AstGlobal *) node;
 
-        if (global->exported_name == NULL)
-            global->exported_name = symbol;
-
         global->name = symbol;
 
     } else if (node->kind != Ast_Kind_Overloaded_Function
@@ -2306,6 +2287,16 @@ static void parse_top_level_statement(OnyxParser* parser) {
                 ENTITY_SUBMIT(add_overload);
                 return;
             }
+            else if (parse_possible_directive(parser, "export")) {
+                AstDirectiveExport *export = make_node(AstDirectiveExport, Ast_Kind_Directive_Export);
+                export->token = dir_token;
+                export->export_name = expect_token(parser, Token_Type_Literal_String);
+
+                export->export = parse_expression(parser, 0);
+
+                ENTITY_SUBMIT(export);
+                return;
+            }
             else {
                 OnyxToken* directive_token = expect_token(parser, '#');
                 OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
index 240a06ce7aff61af60c85dd0ffb04f3dc9da3d00..ee64296b069db953f8f8529eb2c408c826116520 100644 (file)
@@ -1045,6 +1045,20 @@ static SymresStatus symres_process_directive(AstNode* directive) {
             bh_arr_push(operator_overloads[operator->operator], operator->overload);
             break;
         }
+
+        case Ast_Kind_Directive_Export: {
+            AstDirectiveExport *export = (AstDirectiveExport *) directive;
+            SYMRES(expression, &export->export);
+
+            export->export->flags |= Ast_Flag_Exported;
+
+            if (export->export->kind == Ast_Kind_Function) {
+                AstFunction *func = (AstFunction *) export->export;
+                func->exported_name = export->export_name;
+            }
+
+            break;
+        }
     }
 
     return Symres_Success;
@@ -1109,7 +1123,6 @@ void symres_entity(Entity* ent) {
         case Entity_Type_String_Literal:          ss = symres_expression(&ent->expr); break;
         case Entity_Type_Struct_Member_Default:   ss = symres_struct_defaults((AstType *) ent->type_alias); break;
         case Entity_Type_Process_Directive:       ss = symres_process_directive((AstNode *) ent->expr);
-                                                  next_state = Entity_State_Finalized;
                                                   break;
 
         default: break;
index 49f9044d87e6260953695f870bbcf21177c9a0ea..143d0e19d06044438ba5f16654e4c7e531692088 100644 (file)
@@ -2756,19 +2756,6 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) {
 
     i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) fd);
 
-    if (fd->flags & Ast_Flag_Exported) {
-        token_toggle_end(fd->exported_name);
-
-        WasmExport wasm_export = {
-            .kind = WASM_FOREIGN_FUNCTION,
-            .idx = func_idx,
-        };
-        bh_table_put(WasmExport, mod->exports, fd->exported_name->text, wasm_export);
-        mod->export_count++;
-
-        token_toggle_end(fd->exported_name);
-    }
-
     // If there is no body then don't process the code
     if (fd->body != NULL) {
         // NOTE: Generate the local map
@@ -2853,6 +2840,32 @@ static void emit_foreign_function(OnyxWasmModule* mod, AstFunction* fd) {
     return;
 }
 
+static void emit_export_directive(OnyxWasmModule* mod, AstDirectiveExport* export) {
+    assert(export->export_name);
+    assert(export->export);
+
+    token_toggle_end(export->export_name);
+
+    i64 idx = bh_imap_get(&mod->index_map, (u64) export->export);
+
+    WasmExport wasm_export;
+    wasm_export.idx = (i32) idx;
+
+    switch (export->export->kind) {
+        case Ast_Kind_Function: wasm_export.kind = WASM_FOREIGN_FUNCTION;
+                                break;
+
+        case Ast_Kind_Global:   wasm_export.kind = WASM_FOREIGN_GLOBAL;
+                                break;
+    }
+
+    bh_table_put(WasmExport, mod->exports, export->export_name->text, wasm_export);
+    mod->export_count++;
+    
+    token_toggle_end(export->export_name);
+    return;
+}
+
 static void emit_global(OnyxWasmModule* module, AstGlobal* global) {
     WasmType global_type = onyx_type_to_wasm_type(global->type);
 
@@ -2864,19 +2877,6 @@ static void emit_global(OnyxWasmModule* module, AstGlobal* global) {
 
     i32 global_idx = (i32) bh_imap_get(&module->index_map, (u64) global);
 
-    if ((global->flags & Ast_Flag_Exported) != 0) {
-        token_toggle_end(global->exported_name);
-
-        WasmExport wasm_export = {
-            .kind = WASM_FOREIGN_GLOBAL,
-            .idx = global_idx,
-        };
-        bh_table_put(WasmExport, module->exports, global->exported_name->text, wasm_export);
-        module->export_count++;
-
-        token_toggle_end(global->exported_name);
-    }
-
     bh_arr_new(global_heap_allocator, glob.initial_value, 1);
 
     switch (global_type) {
@@ -3274,6 +3274,13 @@ void emit_entity(Entity* ent) {
             break;
         }
 
+        case Entity_Type_Process_Directive: {
+            if (ent->expr->kind == Ast_Kind_Directive_Export) {
+                emit_export_directive(module, (AstDirectiveExport *) ent->expr);
+            }
+            break;
+        }
+
         case Entity_Type_Function: emit_function(module, ent->function); break;
         case Entity_Type_Global:   emit_global(module,   ent->global); break;