aboutsummaryrefslogtreecommitdiff
path: root/ast.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-17 16:20:30 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-17 16:20:30 -0400
commit03a7d5f44dfd8c455706b2c5c23217fd140f18c2 (patch)
tree55cca3cb1c1772af5a74a5b779bb22580d449c9b /ast.c
parentaaa51fc734dde35ab8109bad04e478cdf4fff950 (diff)
Overhaul of header logic so it now uses topological ordering and
deduplication for libraries with multiple files.
Diffstat (limited to 'ast.c')
-rw-r--r--ast.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/ast.c b/ast.c
index b4a75277..0d2d6e5b 100644
--- a/ast.c
+++ b/ast.c
@@ -1,8 +1,8 @@
// Some basic operations defined on AST nodes, mainly converting to
// strings for debugging.
#include <gc/cord.h>
-#include <stdarg.h>
#include <printf.h>
+#include <stdarg.h>
#include "ast.h"
#include "stdlib/datatypes.h"
@@ -264,9 +264,11 @@ void _visit_topologically(ast_t *ast, Table_t definitions, Table_t *visited, Clo
void visit_topologically(ast_list_t *asts, Closure_t fn)
{
- // Visit each top-level statement in topological order, where typedefs are
- // visited first, and each typedef's referenced types are visited before it
- // is, when applicable.
+ // Visit each top-level statement in topological order:
+ // - 'use' statements first
+ // - then typedefs
+ // - visiting typedefs' dependencies first
+ // - then function/variable declarations
Table_t definitions = {};
for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
@@ -282,14 +284,24 @@ void visit_topologically(ast_list_t *asts, Closure_t fn)
}
}
+ void (*visit)(void*, ast_t*) = (void*)fn.fn;
Table_t visited = {};
+ // First: 'use' statements in order:
+ for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
+ if (stmt->ast->tag == Use || (stmt->ast->tag == Declare && Match(stmt->ast, Declare)->value->tag == Use))
+ visit(fn.userdata, stmt->ast);
+ }
+ // Then typedefs in topological order:
for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
if (stmt->ast->tag == StructDef || stmt->ast->tag == EnumDef || stmt->ast->tag == LangDef)
_visit_topologically(stmt->ast, definitions, &visited, fn);
}
+ // Then everything else in order:
for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
- if (!(stmt->ast->tag == StructDef || stmt->ast->tag == EnumDef || stmt->ast->tag == LangDef))
- _visit_topologically(stmt->ast, definitions, &visited, fn);
+ if (!(stmt->ast->tag == StructDef || stmt->ast->tag == EnumDef || stmt->ast->tag == LangDef
+ || stmt->ast->tag == Use || (stmt->ast->tag == Declare && Match(stmt->ast, Declare)->value->tag == Use))) {
+ visit(fn.userdata, stmt->ast);
+ }
}
}