Files
avcf/codegen/index.js
T
adrien 35959784de refactor: flat DFA code generation — every block is a label, every edge is a goto
Replace the nested if-else branch-analysis architecture with a flat DFA
model using CodeGen.emitFlat — a single DFS walk emitting each block as
a C label followed by its code and gotos to all successors.

Removed:
- _branchDescendants / emitBranch / generateCallWithError
- _generateCallWithError, _noWalkNext, _genVisited
- generateNextCode, findBackEdges
- WCDecision._branchDescendants / _emitBranch / overridden generateCode

Added:
- CodeGen.emitFlat(entry) — flat DFS emit with labels + gotos
- WCBlock.generateFlowCode() — base emits gotos from wcNextFlow
- WCDecision.generateFlowCode() — if-goto / goto for decisions
- WCProcCall.generateFlowCode() — if (call != 0) goto err / goto ok

Output is flat — zero nested if-else for branch/error handling.
Tests use local out/ directory.
2026-06-23 03:21:22 +02:00

92 lines
2.9 KiB
JavaScript

// ── Pure C code generation — zero-DOM, flat DFA model ─────────────────
//
// Every block is a C label. Every flow edge is a `goto label;`.
// There is zero nesting: no if/else chains, no branch-analysis, no
// shared-block computation. Decisions become `if (cond) goto yes;
// goto no;`. Error handling becomes `if (call != 0) goto err;
// goto ok;`.
//
// Block interface:
// { id: string,
// generateOwnCode(): string, // C code for this one block
// generateFlowCode?(): string, // flow-control (gotos). If absent,
// // CodeGen walks wcNextFlow instead.
// wcNextFlow?: [{toElement: block}],
// nextFlow?: [{toElement: block}] }
(function () {
"use strict";
var CodeGen = {};
/**
* Emits a complete C program as a flat sequence of labelled blocks
* connected by gotos. Each block is emitted once (DFS order); already-
* visited blocks become `goto label;` stubs.
*
* @param {Object} entry the first block (e.g. START)
* @returns {string}
*/
CodeGen.emitFlat = function (entry) {
var visited = new Set();
var parts = [];
function emit(block) {
if (visited.has(block)) {
parts.push(" goto " + block.id + ";\n");
return;
}
visited.add(block);
parts.push("\n" + block.id + ":");
var own = block.generateOwnCode();
if (own) parts.push(own);
// Flow control: custom generateFlowCode, or auto from wcNextFlow
var flow = block.wcNextFlow || block.nextFlow || [];
var fc = "";
if (typeof block.generateFlowCode === "function") {
fc = block.generateFlowCode();
} else {
for (var i = 0; i < flow.length; i++) {
var t = flow[i].toElement;
if (t) fc += " goto " + t.id + ";\n";
}
}
if (fc) parts.push("\n" + fc);
// Recurse into successors (visited blocks are skipped at top)
for (var i = 0; i < flow.length; i++) {
var t = flow[i].toElement;
if (t) emit(t);
}
}
emit(entry);
return parts.join("");
};
/**
* Assembles a complete C source file.
*/
CodeGen.generateCFile = function (entryBlock, includes, declarations) {
var lines = ["// --- WiseCode\u00ae ---"];
for (var i = 0; i < includes.length; i++) lines.push(includes[i]);
lines.push("");
lines.push("int main() {");
if (declarations) lines.push(declarations);
lines.push(CodeGen.emitFlat(entryBlock));
lines.push("}");
lines.push("// --- END ---");
return lines.join("\n");
};
// ── Export ──────────────────────────────────────────────────────────
if (typeof module !== "undefined" && module.exports) {
module.exports = CodeGen;
}
if (typeof window !== "undefined") {
window.CodeGen = CodeGen;
}
})();