package expressions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 13 Apr 2021 23:48:54 +0000 (18:48 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 13 Apr 2021 23:48:54 +0000 (18:48 -0500)
19 files changed:
bin/onyx
core/array.onyx
core/builtin.onyx
core/env.onyx
core/intrinsics/simd.onyx
core/io/file.onyx
core/io/writer.onyx
core/js/webgl.onyx
core/map.onyx
core/math.onyx
core/runtime/js.onyx
core/runtime/wasi.onyx
core/std.onyx
core/stdio.onyx
core/string/builder.onyx
include/onyxastnodes.h
src/onyxparser.c
src/onyxsymres.c
src/onyxutils.c

index d65379e6bef26769a5cc99665db366d6b4eee585..ca0e7fbf7d2e656e2319aba58b8a08701418f8ff 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 472c662a9b6e9a99853d0bc54b52d65db416456f..da19673215bb181e311b14906d3938f0b5245562 100644 (file)
@@ -1,5 +1,14 @@
 package core.array
 
+// [..] T == Array(T)
+//   where
+// Array :: struct (T: type_expr) {
+//     data      : T;
+//     count     : u32;
+//     capacity  : u32;
+//     allocator : Allocator;
+// }
+
 // ---------------------------------
 //           Dynamic Arrays
 // ---------------------------------
@@ -171,8 +180,18 @@ fold :: proc {
     }
 }
 
-map :: (arr: ^[..] $T, data: $R, f: (T, R) -> T) {
-    for ^it: *arr do *it = f(*it, data);
+map :: proc {
+    (arr: ^[..] $T, f: (T) -> T) {
+        for ^it: *arr do *it = f(*it);
+    },
+
+    (arr: ^[..] $T, f: (^T) -> void) {
+        for ^it: *arr do f(it);
+    },
+
+    (arr: ^[..] $T, data: $R, f: (T, R) -> T) {
+        for ^it: *arr do *it = f(*it, data);
+    },
 }
 
 #private_file
index aa742eb842f590813f2a67e7b847632fee044f23..e0ba37041b95a6433f4bf96e5bf9001102761ee2 100644 (file)
@@ -3,7 +3,7 @@ package builtin
 // CLEANUP: Should builtin.onyx really be including other files in the compilation?
 // Does that complicate things too much?
 #load "core/runtime/build_opts"
-use package runtime as runtime
+#private_file runtime :: package runtime
 
 str  :: #type []u8;
 cstr :: #type ^u8;
index e1b2770cbd7fa5b3ce2995739ce79fc17c03e9bf..568dea4548c65a6d70ab133e948229221cf7875b 100644 (file)
@@ -1,15 +1,14 @@
 package core.env
 
-use package runtime as runtime
-#if runtime.Runtime != runtime.Runtime_Wasi {
+#if (package runtime).Runtime != (package runtime).Runtime_Wasi {
     #error "'core.env' is only available with the 'wasi' runtime.";
 }
 
 
 use package wasi { environ_get, environ_sizes_get, Size }
-use package core.map as map
-use package core.memory as memory
-use package core.string as string
+#private map    :: package core.map
+#private memory :: package core.memory
+#private string :: package core.string
 
 Environment :: struct {
     vars             : map.Map(str, str);
index 55297ad4005081cf78a27f704b099c21ee9866a2..adf65f538a6655afeae7fb6dbf58d00e4a21155b 100644 (file)
@@ -1,6 +1,6 @@
 package core.intrinsics.simd
 
-use package simd as simd
+simd :: package simd
 
 i8x16 :: #type simd.i8x16
 i16x8 :: #type simd.i16x8
index 36d7b404ffe41993920c1f119973b540235f85e7..cee57a7db3926b55b3c1f49927ee37de1fc3c8a7 100644 (file)
@@ -6,7 +6,8 @@ use package runtime as runtime
 }
 
 use package core
-use package wasi as wasi
+
+#private_file wasi :: package wasi
 use package wasi {
     FileDescriptor,
     FDFlags, OFlags, Rights,
index 374572e5c89702f2d2b94f8b1124c3f3f5356737..53dc88e5ae9be301046f872a645c710fdff259ec 100644 (file)
@@ -1,6 +1,6 @@
 package core.io
 
-use package core.conv as conv
+#private_file conv :: package core.conv
 
 Writer :: struct {
     stream : ^Stream;
index b0befbef181ef5087263185491f7f12a4164bef9..8ec5a144a86e9186155feda88ab470ed22c6333a 100644 (file)
@@ -3,7 +3,7 @@ package gl
 // To be used with the corresponding gl.js
 // There are many things that are missing but this suffices for me.
 
-use package runtime as runtime
+#private_file runtime :: package runtime
 #if runtime.Runtime != runtime.Runtime_Js {
     #error "'webgl' can only be used with the 'js' runtime."
 }
index e8ac3db8939643f966a990ce7bc8f792a192317c..1153597a351e582ee05abf82ee31387ff217501f 100644 (file)
@@ -1,7 +1,7 @@
 package core.map
 
-use package core.array as array
-use package core.string as string
+#private_file array  :: package core.array
+#private_file string :: package core.string
 
 Map :: struct (K: type_expr, V: type_expr) {
     hashes  : [..] i32;
index b7b48a5782401a6df177400800727d3c6198a842..1fc8a7a818dee884cac907f3ecb4660fc162db2c 100644 (file)
@@ -1,6 +1,6 @@
 package core.math
 
-use package core.intrinsics.wasm as wasm
+#private_file wasm :: package core.intrinsics.wasm
 
 // Things that are useful in any math library:
 //  - Trigonometry
index 2891881decad7ee8ad41b599b1a44be198468674..f109614fc8d2395771a5f92182b9f5ae40eb3f1f 100644 (file)
@@ -3,7 +3,6 @@ package runtime
 #load "core/runtime/common"
 
 use package core
-use package main as main
 
 __output_string :: (s: str) -> u32 #foreign "host" "print_str" ---
 __exit          :: (status: i32) -> void #foreign "host" "exit" ---
@@ -14,7 +13,7 @@ _start :: () -> void #export "_start" {
     __runtime_initialize();
 
     args: [] cstr = .{ null, 0 };
-    main.main(args);
+    (package main).main(args);
 
     __flush_stdio();
 }
index a28b73cfae9bd6bfb39ce9fbe323692b84f9ef0b..c6a2039962cb159314a36353751e5b4a05bcb166 100644 (file)
@@ -5,7 +5,6 @@ package runtime
 
 use package wasi
 use package core
-use package main as main
 
 __output_string :: (s: str) -> u32 {
     STDOUT_FILENO :: 1
@@ -46,7 +45,7 @@ _start :: () -> void #export "_start" {
         args[i] = cast(cstr) (cast(^u32) args.data)[i];
     }
 
-    main.main(args);
+    (package main).main(args);
 
     __flush_stdio();
 }
index d10f13e1edf6376b48ddb36ebcad561c1f826b77..2632c73c3187bf84d90a62733c4808b9da5055b6 100644 (file)
@@ -27,7 +27,7 @@ package core
 #load "core/runtime/build_opts"
 #load "core/runtime/common"
 
-use package runtime as runtime
+#private_file runtime :: package runtime
 #if runtime.Runtime == runtime.Runtime_Wasi {
     #load "core/runtime/wasi"
     #load "core/wasi"
index f272143768f134cdee61a1ecdc5da59bb0571e5b..f92d4603f1c03a918a0d90857109725d1786618e 100644 (file)
@@ -7,7 +7,7 @@ package core
 // in anyway.
 
 
-use package runtime as runtime
+#private_file runtime :: package runtime
 #if runtime.Runtime == runtime.Runtime_Custom {
     #error "'stdio' can only be included in the 'wasi' or 'js' runtime."
 }
index 575a296e395f1a30eb47b1167a2921737a78433d..3f15861abf0970755c34dc6399cf7ccdf739c171 100644 (file)
@@ -3,9 +3,9 @@ package core.string.builder
 // DEPRECATED: This package is deprecated in favor of using
 // an io.DynamicStringStream with an io.Writer.
 
-use package core.array as array
-use package core.string as string
-use package core.conv as conv
+#private_file array  :: package core.array
+#private_file string :: package core.string
+#private_file conv   :: package core.conv
 
 Builder :: struct {
     data  : [..] u8;
index c010109ef537a73ad0d30eb07639f3e36985d3d4..cdd4047c280a237dcc9ac5eadf41a4cf66bfab10 100644 (file)
@@ -712,8 +712,7 @@ struct AstInclude       { AstNode_base; char* name; };
 struct AstUsePackage    {
     AstNode_base;
 
-    OnyxToken *package_name;
-    Package *package;
+    AstPackage *package;
 
     OnyxToken *alias;
     AstPackage *alias_node;
@@ -803,7 +802,10 @@ struct AstPackage {
     AstNode_base;
 
     // Allocated in the ast arena
-    char* package_name;
+    char * package_name;
+
+    // NOTE: Symbol nodes
+    bh_arr(OnyxToken *) path;
 
     Package* package;
 };
index 25c9314be2eacd13f8e6a4270ef77c23a8c2dfa2..f878f16ae1109d766f1346da45efe27159c3319a 100644 (file)
@@ -67,7 +67,7 @@ static AstEnumType*   parse_enum_declaration(OnyxParser* parser);
 static AstTyped*      parse_top_level_expression(OnyxParser* parser);
 static AstBinding*    parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol);
 static void           parse_top_level_statement(OnyxParser* parser);
-static AstPackage*    parse_package_name(OnyxParser* parser);
+static AstPackage*    parse_package_expression(OnyxParser* parser);
 
 static void consume_token(OnyxParser* parser) {
     if (parser->hit_unexpected_token) return;
@@ -459,11 +459,10 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             break;
         }
 
-        // case Token_Type_Keyword_Package: {
-        //     AstPackage* package_node = make_node(AstPackage, Ast_Kind_Package);
-        //     package_node->token
-        //     break;
-        // }
+        case Token_Type_Keyword_Package: {
+            retval = (AstTyped *) parse_package_expression(parser);
+            break;
+        }
 
         // :TypeValueInterchange
         case '<': {
@@ -1156,29 +1155,10 @@ static AstReturn* parse_return_stmt(OnyxParser* parser) {
 static AstNode* parse_use_stmt(OnyxParser* parser) {
     OnyxToken* use_token = expect_token(parser, Token_Type_Keyword_Use);
 
-    if (consume_token_if_next(parser, Token_Type_Keyword_Package)) {
-        // CLEANUP: This logic should be acceptable but because parse_package_name
-        // will declare and initialize packages as it parses them. There should be
-        // some reusable logic to be pulled out of it however.
-        // AstUsePackage* upack = make_node(AstUsePackage, Ast_Kind_Use_Package);
-        // upack->token = use_token;
-        // upack->package = parse_package_name(parser);
-
+    if (parser->curr->type == Token_Type_Keyword_Package) {
         AstUsePackage* upack = make_node(AstUsePackage, Ast_Kind_Use_Package);
         upack->token = use_token;
-
-        OnyxToken* package_name = expect_token(parser, Token_Type_Symbol);
-
-        // CLEANUP: This is just gross.
-        while (consume_token_if_next(parser, '.')) {
-            if (parser->hit_unexpected_token) break;
-            package_name->length += 1;
-
-            OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
-            package_name->length += symbol->length;
-        }
-
-        upack->package_name = package_name;
+        upack->package = parse_package_expression(parser);
 
         if (consume_token_if_next(parser, Token_Type_Keyword_As))
             upack->alias = expect_token(parser, Token_Type_Symbol);
@@ -2351,60 +2331,85 @@ submit_binding_to_entities:
     }
 }
 
-static AstPackage* parse_package_name(OnyxParser* parser) {
+static AstPackage* parse_package_expression(OnyxParser* parser) {
     AstPackage* package_node = make_node(AstPackage, Ast_Kind_Package);
-
-    if (parser->curr->type != Token_Type_Keyword_Package) {
-        Package *package = package_lookup_or_create("main", context.global_scope, parser->allocator);
-
-        package_node->token = NULL;
-        package_node->package = package;
-        return package_node;
-    }
-    
-    // CLEANUP
-    char package_name[1024]; // CLEANUP: This could overflow, if someone decides to be dumb
-                             // with their package names  - brendanfh   2020/12/06
-    package_name[0] = 0;
     package_node->token = expect_token(parser, Token_Type_Keyword_Package);
 
-    Package *package = NULL;
+    bh_arr_new(global_heap_allocator, package_node->path, 2);
 
-    while (1) {
+    while (parser->curr->type == Token_Type_Symbol) {
         if (parser->hit_unexpected_token) return package_node;
 
         OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
 
-        // This logic will need to accessible elsewhere
-        token_toggle_end(symbol);
-        strncat(package_name, symbol->text, 1023);
-        token_toggle_end(symbol);
+        bh_arr_push(package_node->path, symbol);
+        
+        if (consume_token_if_next(parser, '.'));
+        else break;
+    }
 
-        Package *newpackage = package_lookup_or_create(package_name, context.global_scope, parser->allocator);
+    i32 total_package_name_length = 0;
+    bh_arr_each(OnyxToken *, token, package_node->path) {
+        total_package_name_length += (*token)->length + 1;
+    }
 
-        if (package != NULL) {
-            AstPackage* pnode = make_node(AstPackage, Ast_Kind_Package);
-            pnode->token = symbol;
-            pnode->package = newpackage;
+    char* package_name = bh_alloc_array(context.ast_alloc, char, total_package_name_length); 
+    *package_name = '\0';
 
-            token_toggle_end(symbol);
-            symbol_subpackage_introduce(package->scope, symbol->text, pnode);
-            token_toggle_end(symbol);
+    bh_arr_each(OnyxToken *, token, package_node->path) {
+        token_toggle_end(*token);
+        strncat(package_name, (*token)->text, total_package_name_length - 1);
+        token_toggle_end(*token);
 
-            package_reinsert_use_packages(package);
+        if (token != &bh_arr_last(package_node->path)) {
+            strncat(package_name, ".", total_package_name_length - 1);
         }
-
-        package = newpackage;
-
-        if (consume_token_if_next(parser, '.')) strncat(package_name, ".", 1023);
-        else break;
     }
 
-    package_node->package = package;
+    package_node->package_name = package_name;
+    package_node->package = package_lookup(package_name);
+
     return package_node;
 }
 
+static Package* parse_file_package(OnyxParser* parser) {
+    if (parser->curr->type != Token_Type_Keyword_Package) {
+        return package_lookup_or_create("main", context.global_scope, parser->allocator);
+    }
+
+    AstPackage* package_node = parse_package_expression(parser);
+    
+    char aggregate_name[2048];
+    aggregate_name[0] = '\0';
+
+    Package* prevpackage = NULL;
 
+    bh_arr_each(OnyxToken *, symbol, package_node->path) {
+        token_toggle_end(*symbol);
+
+        strncat(aggregate_name, (*symbol)->text, 2047);
+        Package* newpackage = package_lookup_or_create(aggregate_name, context.global_scope, parser->allocator);
+        
+        AstPackage* pnode = make_node(AstPackage, Ast_Kind_Package);
+        pnode->token = *symbol;
+        pnode->package = newpackage;
+        pnode->package_name = newpackage->name;
+
+        if (prevpackage != NULL) {
+            symbol_subpackage_introduce(prevpackage->scope, (*symbol)->text, pnode);
+            package_reinsert_use_packages(prevpackage);
+        }
+
+        token_toggle_end(*symbol);
+        strncat(aggregate_name, ".", 2047);
+
+        prevpackage = newpackage;
+    }
+
+    package_node->package = prevpackage;
+    
+    return package_node->package;
+}
 
 
 // NOTE: This returns a void* so I don't need to cast it everytime I use it
@@ -2447,12 +2452,14 @@ void onyx_parse(OnyxParser *parser) {
     // NOTE: Skip comments at the beginning of the file
     while (consume_token_if_next(parser, Token_Type_Comment));
 
-    parser->package = parse_package_name(parser)->package;
+    parser->package = parse_file_package(parser);
     parser->file_scope = scope_create(parser->allocator, parser->package->private_scope, parser->tokenizer->tokens[0].pos);
     bh_arr_push(parser->scope_stack, parser->file_scope);
 
     AstUsePackage* implicit_use_builtin = make_node(AstUsePackage, Ast_Kind_Use_Package);
-    implicit_use_builtin->package_name = &builtin_package_token;
+    AstPackage* implicit_builtin_package = make_node(AstPackage, Ast_Kind_Package);
+    implicit_builtin_package->package_name = "builtin";
+    implicit_use_builtin->package = implicit_builtin_package;
     ENTITY_SUBMIT(implicit_use_builtin);
 
     while (parser->curr->type != Token_Type_End_Stream) {
index beaa48068afa918d5aff6681dd920c8e5bba5d84..80bcb118af7f5db432142e6ffa598149f0f2a452 100644 (file)
@@ -53,6 +53,7 @@ static SymresStatus symres_function(AstFunction* func);
 static SymresStatus symres_global(AstGlobal* global);
 static SymresStatus symres_overloaded_function(AstOverloadedFunction* ofunc);
 static SymresStatus symres_use_package(AstUsePackage* package);
+static SymresStatus symres_package(AstPackage* package);
 static SymresStatus symres_enum(AstEnumType* enum_node);
 static SymresStatus symres_memres_type(AstMemRes** memres);
 static SymresStatus symres_memres(AstMemRes** memres);
@@ -487,6 +488,10 @@ static SymresStatus symres_expression(AstTyped** expr) {
             SYMRES(compound, (AstCompound *) *expr);
             break;
 
+        case Ast_Kind_Package:
+            SYMRES(package, (AstPackage *) *expr);
+            break;
+
         default: break;
     }
 
@@ -882,22 +887,10 @@ static SymresStatus symres_overloaded_function(AstOverloadedFunction* ofunc) {
 }
 
 static SymresStatus symres_use_package(AstUsePackage* package) {
-    if (package->package == NULL) {
-        token_toggle_end(package->package_name);
-        package->package = package_lookup(package->package_name->text);
-        token_toggle_end(package->package_name);
-    }
+    SYMRES(package, package->package);
 
-    Package* p = package->package;
-
-    if (p == NULL) { // :SymresStall
-        if (report_unresolved_symbols) {
-            onyx_report_error(package->package_name->pos, "package not found in included source files");
-            return Symres_Error;
-        } else {
-            return Symres_Yield_Macro;
-        }
-    }
+    // CLEANUP: Oofta that name
+    Package* p = package->package->package;
 
     if (p->scope == curr_scope) return Symres_Success;
 
@@ -939,6 +932,27 @@ static SymresStatus symres_use_package(AstUsePackage* package) {
     return Symres_Success;
 }
 
+static SymresStatus symres_package(AstPackage* package) {
+    if (package->package == NULL) {
+        if (!package->package_name) return Symres_Error;
+
+        package->package = package_lookup(package->package_name);
+    }
+
+    if (package->package) {
+        return Symres_Success;
+    } else {
+        if (report_unresolved_symbols) {
+            onyx_report_error(package->token->pos,
+                    "Package '%s' not found in included source files.",
+                    package->package_name);
+            return Symres_Error;
+        } else {
+            return Symres_Yield_Macro;
+        }
+    }
+}
+
 static SymresStatus symres_enum(AstEnumType* enum_node) {
     if (enum_node->backing->kind == Ast_Kind_Symbol) SYMRES(symbol, (AstNode **) &enum_node->backing);
     if (enum_node->backing == NULL) return Symres_Error;
@@ -1087,7 +1101,8 @@ void symres_entity(Entity* ent) {
         case Entity_Type_Global_Header:           ss = symres_global(ent->global); break;
 
         case Entity_Type_Use_Package:             ss = symres_use_package(ent->use_package);
-                                                  if (ent->use_package->package) package_track_use_package(ent->use_package->package, ent);
+                                                  if (ent->use_package->package && ent->use_package->package->package)
+                                                      package_track_use_package(ent->use_package->package->package, ent);
                                                   next_state = Entity_State_Finalized;
                                                   break;
 
index e1557180942add55fd066355f9d5bb7f40418490..92290fdd79e4173ebc3494b11985fd6e83db2b52 100644 (file)
@@ -175,6 +175,12 @@ AstNode* try_symbol_raw_resolve_from_node(AstNode* node, char* symbol) {
     switch (node->kind) {
         case Ast_Kind_Package: {
             AstPackage* package = (AstPackage *) node;
+
+            // CLEANUP
+            if (package->package == NULL) {
+                package->package = package_lookup(package->package_name);
+            }
+
             return symbol_raw_resolve(package->package->scope, symbol);
         }