Refactor recursive build mechanism

This commit is contained in:
be5invis 2022-12-19 07:46:41 -08:00
parent 5b359dbbfe
commit 2d938dd309
11 changed files with 153 additions and 105 deletions

View file

@ -1,6 +1,69 @@
export class RecursiveBuildFilter {
constructor(glyphIdFilter) {
this.glyphIdFilter = glyphIdFilter;
}
glyphIsNeeded(id) {
return this.glyphIdFilter.has(id);
}
}
export class DependencyManager {
constructor() {
this.glyphToGlyph = new WeakMap();
this.glyphToBlock = new WeakMap();
}
addDependency(dependent, dependency) {
let s = this.glyphToGlyph.get(dependent);
if (!s) {
s = new Set();
this.glyphToGlyph.set(dependent, s);
}
s.add(dependency);
}
traverseDependencies(glyphs) {
let state = new Map();
const PENDING = 1,
CHECKED = 2;
for (const glyph of glyphs) state.set(glyph, PENDING);
for (;;) {
let found = false;
for (const [glyph, s] of state) {
if (s !== PENDING) continue;
const deps = this.glyphToGlyph.get(glyph);
if (deps) {
for (const g of deps) state.set(g, PENDING);
found = true;
}
state.set(glyph, CHECKED);
}
if (!found) break;
}
let glyphIdFilter = new Set();
for (const g of state.keys()) {
if (g.identifier) glyphIdFilter.add(g.identifier);
}
return new RecursiveBuildFilter(glyphIdFilter);
}
}
export class GlyphBlockExecState {
constructor() {
this.currentBlockName = null;
this.dependencyManager = new DependencyManager();
}
setGlyphToBlockDependency(glyph) {
if (this.currentBlockName) {
this.dependencyManager.glyphToBlock.set(glyph, this.currentBlockName);
}
}
}
export class GlyphBlock {
constructor(capture, blockName, body) {
constructor(capture, execState, blockName, body) {
this.capture = capture;
this.execState = execState;
this.blockName = blockName;
this.body = body;
this.resolved = false;
@ -8,6 +71,10 @@ export class GlyphBlock {
}
resolve() {
if (this.resolved) return this.exports;
const prevBlockName = this.execState.currentBlockName;
this.execState.currentBlockName = this.blockName;
this.resolved = true;
const pendingApplications = [];
const ExportCapture = fnObj => {
@ -19,6 +86,8 @@ export class GlyphBlock {
};
this.body(this.capture, ExportCapture);
for (const f of pendingApplications) f();
this.execState.currentBlockName = prevBlockName;
return this.exports;
}
}