tacker

a simple web bundler
git clone https://tongong.net/git/tacker.git
Log | Files | Refs | README

commit 7b790c499dad708b29cca419fc751ddedc3f70c3
parent 46ab97143c1007b0cd7d43b7ed2859e864a40be0
Author: tongong <tongong@gmx.net>
Date:   Sat, 16 Jul 2022 07:52:21 +0200

implemented kahn's algorithm

Diffstat:
Mbundle_js.ha | 56+++++++++++++++++++++++++++++++++++++++++++++++++-------
Mtest-page/a.js | 1+
Mtest-page/b.js | 1+
Mtest-page/c.js | 3++-
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 = ":)";