commit 7b790c499dad708b29cca419fc751ddedc3f70c3
parent 46ab97143c1007b0cd7d43b7ed2859e864a40be0
Author: tongong <tongong@gmx.net>
Date: Sat, 16 Jul 2022 07:52:21 +0200
implemented kahn's algorithm
Diffstat:
4 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/bundle_js.ha b/bundle_js.ha
@@ -33,13 +33,8 @@ fn dep_graph_free(g: dep_graph) void = {
// inputs are borrowed
fn tacker_js(inputpath: str, ofile: io::handle, html: bool) void = {
let g: dep_graph = [];
- defer {
- for (let i = 0z; i < len(g); i += 1)
- free(g[i].dependencies);
- free(g);
- };
+ defer dep_graph_free(g);
dep_add(void, inputpath, &g);
- // TODO
for (let i = 0z; i < len(g); i += 1) {
fmt::printf("{}: {} - ", i, g[i].path)!;
const dep = g[i].dependencies;
@@ -48,7 +43,12 @@ fn tacker_js(inputpath: str, ofile: io::handle, html: bool) void = {
};
fmt::println("")!;
};
- dep_graph_free(g);
+ const sorting = sort_kahn(g, inputpath);
+ defer free(sorting);
+ fmt::println("sorting:")!;
+ for (let i = 0z; i < len(sorting); i += 1) {
+ fmt::printfln("- {}", g[sorting[i]].path)!;
+ };
};
let p_req: searchio::pattern = searchio::pattern {...};
@@ -180,3 +180,45 @@ fn read_require(in: io::handle, path: str) (str | no) = {
fixed_fatalf("{}: broken require() call.", path);
return ""; // will not be reached
};
+
+// Kahn's algorithm https://en.wikipedia.org/wiki/Topological_sorting
+// Return value has to be freed
+fn sort_kahn(graph: dep_graph, entrypath: str) []size = {
+ let sorting: []size = [];
+ for (let i = 0z; i < len(graph); i += 1) {
+ graph[i].scanned = false;
+ };
+ for (true) {
+ // Find file without dependencies
+ let f = 0z; // index into graph
+ for (f < len(graph); f += 1) {
+ const deps = graph[f].dependencies;
+ let no_deps = true;
+ for (let i = 0z; i < len(deps); i += 1) {
+ // Deleted edges in graph will be set to -1
+ if (deps[i] != -1) {
+ no_deps = false;
+ break;
+ };
+ };
+ if (no_deps && !graph[f].scanned) break;
+ };
+ if (f == len(graph)) {
+ // If no file without dependencies can be found -> error
+ fixed_fatalf("{}: circular javascript dependencies.",
+ entrypath);
+ };
+ // Delete dependencies for dependent files
+ for (let i = 0z; i < len(graph); i += 1) {
+ let deps = graph[i].dependencies;
+ for (let j = 0z; j < len(deps); j += 1) {
+ if (deps[j] == f) deps[j] = -1;
+ };
+ };
+ graph[f].scanned = true;
+ append(sorting, f);
+ // If all files are sorted -> stop
+ if (len(sorting) == len(graph)) return sorting;
+ };
+ return []; // will not be reached
+};
diff --git a/test-page/a.js b/test-page/a.js
@@ -1,4 +1,5 @@
let testm = require("./b.js")
+require("./c.js")
// console.log(testm.hello());
let r = "this require('b.js') will not be macro-expanded.";
diff --git a/test-page/b.js b/test-page/b.js
@@ -1,3 +1,4 @@
+const c = "";
const c = require('./c');
module.exports = {
diff --git a/test-page/c.js b/test-page/c.js
@@ -1,2 +1,3 @@
-console.log(require("./a.js")); // illegal -> circular dependency
+// console.log(require("./a.js")); // illegal -> circular dependency
+require("test-page/b.js");
exports.msg = ":)";