added: `#load_all_recursive`
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 15 May 2023 02:35:34 +0000 (21:35 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 15 May 2023 02:35:34 +0000 (21:35 -0500)
CHANGELOG
compiler/include/astnodes.h
compiler/src/onyx.c
compiler/src/parser.c

index 6e9c5f2197baf52d75f8ecb41f69159f46c28866..b4513b40d884bf158e92b982a83994b3320568ea 100644 (file)
--- 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:
 
index 65dde61d759fa24c923f4e7d8f64be4f6bb5c12f..c88cfc8072c379b89b5d5068bb3843d869cdcc4a 100644 (file)
@@ -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;
index 0a06f397a6b92b6c20f303e3f5f6d61fdff0fff2..d5c98dd38e21d01dc45ac694d7cb104a737dee63 100644 (file)
@@ -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);
index 7f4e5a5fa95d3cda0606642af0b7b0c0e25a1911..2328529b1f4279f1991bef508c41c5396612024b 100644 (file)
@@ -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;