From: Brendan Hansen Date: Tue, 13 Apr 2021 23:48:54 +0000 (-0500) Subject: package expressions X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ee8a128b690f60a74894c2f04d53bd63c3df3aaf;p=onyx.git package expressions --- diff --git a/bin/onyx b/bin/onyx index d65379e6..ca0e7fbf 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/array.onyx b/core/array.onyx index 472c662a..da196732 100644 --- a/core/array.onyx +++ b/core/array.onyx @@ -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 diff --git a/core/builtin.onyx b/core/builtin.onyx index aa742eb8..e0ba3704 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -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; diff --git a/core/env.onyx b/core/env.onyx index e1b2770c..568dea45 100644 --- a/core/env.onyx +++ b/core/env.onyx @@ -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); diff --git a/core/intrinsics/simd.onyx b/core/intrinsics/simd.onyx index 55297ad4..adf65f53 100644 --- a/core/intrinsics/simd.onyx +++ b/core/intrinsics/simd.onyx @@ -1,6 +1,6 @@ package core.intrinsics.simd -use package simd as simd +simd :: package simd i8x16 :: #type simd.i8x16 i16x8 :: #type simd.i16x8 diff --git a/core/io/file.onyx b/core/io/file.onyx index 36d7b404..cee57a7d 100644 --- a/core/io/file.onyx +++ b/core/io/file.onyx @@ -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, diff --git a/core/io/writer.onyx b/core/io/writer.onyx index 374572e5..53dc88e5 100644 --- a/core/io/writer.onyx +++ b/core/io/writer.onyx @@ -1,6 +1,6 @@ package core.io -use package core.conv as conv +#private_file conv :: package core.conv Writer :: struct { stream : ^Stream; diff --git a/core/js/webgl.onyx b/core/js/webgl.onyx index b0befbef..8ec5a144 100644 --- a/core/js/webgl.onyx +++ b/core/js/webgl.onyx @@ -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." } diff --git a/core/map.onyx b/core/map.onyx index e8ac3db8..1153597a 100644 --- a/core/map.onyx +++ b/core/map.onyx @@ -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; diff --git a/core/math.onyx b/core/math.onyx index b7b48a57..1fc8a7a8 100644 --- a/core/math.onyx +++ b/core/math.onyx @@ -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 diff --git a/core/runtime/js.onyx b/core/runtime/js.onyx index 2891881d..f109614f 100644 --- a/core/runtime/js.onyx +++ b/core/runtime/js.onyx @@ -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(); } diff --git a/core/runtime/wasi.onyx b/core/runtime/wasi.onyx index a28b73cf..c6a20399 100644 --- a/core/runtime/wasi.onyx +++ b/core/runtime/wasi.onyx @@ -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(); } diff --git a/core/std.onyx b/core/std.onyx index d10f13e1..2632c73c 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -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" diff --git a/core/stdio.onyx b/core/stdio.onyx index f2721437..f92d4603 100644 --- a/core/stdio.onyx +++ b/core/stdio.onyx @@ -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." } diff --git a/core/string/builder.onyx b/core/string/builder.onyx index 575a296e..3f15861a 100644 --- a/core/string/builder.onyx +++ b/core/string/builder.onyx @@ -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; diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index c010109e..cdd4047c 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -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; }; diff --git a/src/onyxparser.c b/src/onyxparser.c index 25c9314b..f878f16a 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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) { diff --git a/src/onyxsymres.c b/src/onyxsymres.c index beaa4806..80bcb118 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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; diff --git a/src/onyxutils.c b/src/onyxutils.c index e1557180..92290fdd 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -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); }