From 6558da8d3922f384eac388c5071d79039b6a825e Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sun, 14 May 2023 21:35:34 -0500 Subject: [PATCH] added: `#load_all_recursive` --- CHANGELOG | 1 + compiler/include/astnodes.h | 2 +- compiler/src/onyx.c | 57 +++++++++++++++++++++++++------------ compiler/src/parser.c | 9 ++++++ 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6e9c5f21..b4513b40 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ Additions: * `iter.empty` * `json.Value->as_array_iter()`, `json.Value->as_map_iter()` * `onyx pkg new` for creating a project from a template +* `#load_all_recursive` to recursively load all `.onyx` files in a directory. Removals: diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 65dde61d..c88cfc80 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -1057,7 +1057,7 @@ struct AstDistinctType { // Top level nodes struct AstBinding { AstTyped_base; AstNode* node; OnyxToken *documentation; }; struct AstAlias { AstTyped_base; AstTyped* alias; }; -struct AstInclude { AstNode_base; AstTyped* name_node; char* name; }; +struct AstInclude { AstNode_base; AstTyped* name_node; char* name; b32 recursive: 1; }; struct AstInjection { AstTyped_base; AstTyped* full_loc; diff --git a/compiler/src/onyx.c b/compiler/src/onyx.c index 0a06f397..d5c98dd3 100644 --- a/compiler/src/onyx.c +++ b/compiler/src/onyx.c @@ -519,30 +519,51 @@ static b32 process_load_entity(Entity* ent) { bh_snprintf(folder, 511, "%s", include->name); } + bh_path_convert_separators(folder); // This does not take into account #load_path'd folders... + + bh_arr(char *) folders_to_process = NULL; + bh_arr_new(global_heap_allocator, folders_to_process, 2); - bh_path_convert_separators(folder); - bh_dir dir = bh_dir_open(folder); - if (dir == NULL) { - onyx_report_error(include->token->pos, Error_Critical, "Could not find folder '%s'.", folder); - return 0; - } + bh_arr_push(folders_to_process, bh_strdup(global_scratch_allocator, folder)); + + while (bh_arr_length(folders_to_process) > 0) { + char *folder = bh_arr_pop(folders_to_process); + bh_dir dir = bh_dir_open(folder); + if (dir == NULL) { + onyx_report_error(include->token->pos, Error_Critical, "Could not find or open folder '%s'.", folder); + return 0; + } + + bh_dirent entry; + char fullpath[512]; + while (bh_dir_read(dir, &entry)) { + if (entry.type == BH_DIRENT_FILE && bh_str_ends_with(entry.name, ".onyx")) { + bh_snprintf(fullpath, 511, "%s/%s", folder, entry.name); + bh_path_convert_separators(fullpath); - bh_dirent entry; - b32 success = 1; - char fullpath[512]; - while (bh_dir_read(dir, &entry)) { - if (entry.type == BH_DIRENT_FILE && bh_str_ends_with(entry.name, ".onyx")) { - bh_snprintf(fullpath, 511, "%s/%s", folder, entry.name); - bh_path_convert_separators(fullpath); - u8* formatted_name = bh_path_get_full_name(fullpath, global_heap_allocator); - success = process_source_file(formatted_name, include->token->pos); - if (!success) break; + u8* formatted_name = bh_path_get_full_name(fullpath, global_heap_allocator); + + AstInclude* new_include = onyx_ast_node_new(context.ast_alloc, sizeof(AstInclude), Ast_Kind_Load_File); + new_include->token = include->token; + new_include->name = formatted_name; + add_entities_for_node(NULL, (AstNode *) new_include, include->entity->scope, include->entity->package); + } + + if (entry.type == BH_DIRENT_DIRECTORY && include->recursive) { + if (!strcmp(entry.name, ".") || !strcmp(entry.name, "..")) continue; + + bh_snprintf(fullpath, 511, "%s/%s", folder, entry.name); + u8* formatted_name = bh_path_get_full_name(fullpath, global_scratch_allocator); // Could this overflow the scratch allocator? + + bh_arr_push(folders_to_process, formatted_name); + } } + + bh_dir_close(dir); } - bh_dir_close(dir); - return success; + return 1; } else if (include->kind == Ast_Kind_Load_Path) { bh_arr_push(context.options->included_folders, include->name); diff --git a/compiler/src/parser.c b/compiler/src/parser.c index 7f4e5a5f..2328529b 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -3366,6 +3366,15 @@ static void parse_top_level_statement(OnyxParser* parser) { ENTITY_SUBMIT(include); return; } + else if (parse_possible_directive(parser, "load_all_recursive")) { + AstInclude* include = make_node(AstInclude, Ast_Kind_Load_All); + include->token = dir_token; + include->name_node = parse_expression(parser, 0); + include->recursive = 1; + + ENTITY_SUBMIT(include); + return; + } else if (parse_possible_directive(parser, "load_path")) { AstInclude* include = make_node(AstInclude, Ast_Kind_Load_Path); include->token = dir_token; -- 2.25.1