@fs-eire/wgsl-template
Version:
A powerful template system for generating WGSL (WebGPU Shading Language) code with support for parameters, conditionals, and multiple output formats including C++ code generation.
545 lines • 34.4 kB
JavaScript
import { createParamPattern, DEFAULT_PATTERNS, lookupPattern } from "./code-pattern-impl.js";
import { WgslTemplateGenerateError } from "./errors.js";
/**
* Merges adjacent segments of the same type (raw or code) to reduce the number of segments.
* This optimization helps reduce the final emit output size.
*/
function mergeAdjacentSegments(segments) {
return segments.reduce((acc, segment) => {
if (acc.length > 0 &&
acc[acc.length - 1].type === segment.type &&
(segment.type === "raw" || segment.type === "code")) {
// Merge adjacent raw or code segments
acc[acc.length - 1].content += segment.content;
}
else {
// Otherwise, just push the segment
acc.push(segment);
}
return acc;
}, []);
}
function matchNextPattern(content, patterns) {
// Find the pattern that matches earliest in the content
// example:
// content is "abcdefg",
// pattern1 is /cde/, pattern2 is /def/
// the result should be pattern1 (matches at position 2, before pattern2 at position 3)
let earliestMatch = null;
for (const pattern of patterns) {
const regex = typeof pattern.pattern === "string" ? new RegExp(pattern.pattern, "d") : pattern.pattern;
const match = regex.exec(content);
if (match && match.index !== undefined) {
// If this is the first match, or if this match occurs earlier than the current earliest
if (earliestMatch === null || match.index < earliestMatch.index) {
earliestMatch = {
pattern,
index: match.index,
length: match[0].length,
indices: match.indices,
};
}
}
}
return earliestMatch;
}
function generateImpl(generatorState, options) {
const { pass1, codeGenerator, preprocessIfStack, patterns, currentFunctionCall } = generatorState;
let currentLine = generatorState.currentLine;
let currentColumn = generatorState.currentColumn;
let currentParenthesesState = generatorState.currentParenthesesState;
let currentBracketState = generatorState.currentBracketState;
let currentPreProcessorExpression = null;
const output = (type, content) => {
const segment = { type, content };
if (currentPreProcessorExpression !== null) {
if (type === "raw") {
throw new WgslTemplateGenerateError(`Raw content inside preprocessor expression at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
else if (type === "code" && content === "\n") {
// If we are inside a preprocessor expression, EOL means we are done with this expression
}
else {
segment.type = "raw"; // Convert to raw if we are inside a preprocessor expression
currentPreProcessorExpression.push(segment);
}
}
else {
if (currentFunctionCall.length > 0) {
if (type === "raw") {
throw new WgslTemplateGenerateError(`Raw content inside function call at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
// If we are inside a function call, append to the current parameter
currentFunctionCall[currentFunctionCall.length - 1].currentParam.push(segment);
}
else {
generatorState.result.push(segment);
}
}
};
let previousLineWasEmpty = true;
for (let i = 0; i < pass1.length; i++) {
const line = pass1[i].line;
currentLine = i;
currentColumn = 0;
const processCurrentLine = () => {
while (currentColumn < line.length) {
const restLine = line.slice(currentColumn);
const next = matchNextPattern(restLine, patterns);
if (!next)
break;
const indices = next.indices;
if (next.index > 0) {
// Output the text before the matched pattern
output("code", line.slice(currentColumn, currentColumn + next.index));
}
// Process the matched pattern
const matched = line.slice(currentColumn + next.index, currentColumn + next.index + next.length);
currentColumn += next.index + next.length;
let caller;
let name = matched;
switch (next.pattern.type) {
case "control":
if (matched === "(") {
currentParenthesesState++;
output("code", "(");
}
else if (matched === ",") {
if (currentFunctionCall.length > 0 &&
currentFunctionCall[currentFunctionCall.length - 1].parenthesesState + 1 === currentParenthesesState) {
// End of current parameter, push it to params array
const call = currentFunctionCall[currentFunctionCall.length - 1];
if (call.currentParam.length === 0) {
throw new WgslTemplateGenerateError(`Empty parameter at line ${currentLine + 1}, column ${currentColumn}`, "parameter-missing", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
call.params.push(call.currentParam);
call.currentParam = []; // Reset current parameter
}
else {
// Just output the comma
output("code", ",");
}
}
else if (matched === ")") {
currentParenthesesState--;
if (currentParenthesesState < 0) {
throw new WgslTemplateGenerateError(`Unmatched closing parenthesis at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
if (currentFunctionCall.length > 0 &&
currentFunctionCall[currentFunctionCall.length - 1].parenthesesState === currentParenthesesState) {
// End of function call
const call = currentFunctionCall.pop();
if (call) {
if (call.currentParam.length > 0) {
call.params.push(call.currentParam);
}
const params = call.params.map((p) => mergeAdjacentSegments(p));
// Clean up empty code segments in parameters
for (const param of params) {
if (param.at(-1)?.type === "code") {
if (param.at(-1).content.trim() === "") {
param.pop();
}
else {
param.at(-1).content = param.at(-1).content.trimEnd();
}
}
if (param.at(0)?.type === "code") {
if (param.at(0).content.trim() === "") {
param.shift();
}
else {
param.at(0).content = param.at(0).content.trimStart();
}
}
}
const codeSegmentArgs = params.map((param, index) => ({
type: call.argTypes?.[index] ?? "auto",
code: param,
}));
output("expression", call.caller
? codeGenerator.method(call.caller, call.name, codeSegmentArgs)
: codeGenerator.function(call.name, codeSegmentArgs));
}
}
else {
output("code", ")");
}
}
else if (matched === "{") {
currentBracketState++;
output("code", "{");
}
else if (matched === "}") {
currentBracketState--;
if (currentBracketState < 0) {
throw new WgslTemplateGenerateError(`Unmatched closing bracket at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
if (currentBracketState === 0 && generatorState.mainFunction === "started") {
// End of main function context
output("raw", "MainFunctionEnd();\n");
generatorState.mainFunction = "ended";
}
else {
output("code", "}");
}
}
else if (matched.includes("$MAIN")) {
// Special case for $MAIN, which indicates the main function context
if (generatorState.mainFunction !== "not-started") {
throw new WgslTemplateGenerateError(`Multiple main function start ($MAIN) detected at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
if (currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`$MAIN directive inside function call at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
if (currentParenthesesState !== 0) {
throw new WgslTemplateGenerateError(`$MAIN directive inside parentheses at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
if (currentBracketState !== 0) {
throw new WgslTemplateGenerateError(`$MAIN directive inside brackets at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
if (currentPreProcessorExpression !== null) {
throw new WgslTemplateGenerateError(`$MAIN directive inside preprocessor expression at line ${currentLine + 1}, column ${currentColumn}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
generatorState.mainFunction = "started";
output("raw", "MainFunctionStart();\n");
currentBracketState = 1; // Start a new bracket context for the main function
}
break;
case "param":
generatorState.usedParams.set(matched, next.pattern.paramType || "int");
output("expression", codeGenerator.param(matched));
break;
case "variable":
let variableName = matched;
if (next.pattern.replace && Array.isArray(next.pattern.replace) && next.pattern.replace[0]) {
variableName = next.pattern.replace[0];
}
generatorState.usedVariables.set(variableName, next.pattern.variableType || "shader-variable");
output("expression", codeGenerator.variable(variableName));
break;
case "method":
if (next.pattern.replace && Array.isArray(next.pattern.replace) && next.pattern.replace[0]) {
caller = next.pattern.replace[0];
}
else {
caller = restLine.slice(indices[1][0], indices[1][1]);
}
// Track the object variable for method calls
generatorState.usedVariables.set(caller, next.pattern.variableType || "shader-variable");
case "function":
// Handle function/method patterns
if (next.pattern.replace && Array.isArray(next.pattern.replace) && next.pattern.replace[caller ? 1 : 0]) {
name = next.pattern.replace[caller ? 1 : 0];
}
else {
name = restLine.slice(indices[caller ? 2 : 1][0], indices[caller ? 2 : 1][1]);
}
currentFunctionCall.push({
name,
parenthesesState: currentParenthesesState,
params: [],
currentParam: [],
caller,
argTypes: next.pattern.argTypes,
});
currentParenthesesState++;
break;
case "property":
if (next.pattern.replace && Array.isArray(next.pattern.replace) && next.pattern.replace[0]) {
caller = next.pattern.replace[0];
}
else {
caller = restLine.slice(indices[1][0], indices[1][1]);
}
// Track the object variable for property access
generatorState.usedVariables.set(caller, next.pattern.variableType || "shader-variable");
if (next.pattern.replace && Array.isArray(next.pattern.replace) && next.pattern.replace[1]) {
name = next.pattern.replace[1];
}
else {
name = restLine.slice(indices[2][0], indices[2][1]);
}
output("expression", codeGenerator.property(caller, name));
break;
}
}
if (currentColumn < line.length) {
// Output any remaining text after the last matched pattern
output("code", line.slice(currentColumn));
}
output("code", "\n");
};
if (options.preserveCodeReference) {
const maxLineNumber = pass1.length;
const lineNumberWidth = String(maxLineNumber).length;
const paddedLineNumber = String(currentLine + 1).padStart(lineNumberWidth, " ");
const sourcePath = pass1[i].codeReference.filePath;
const sourceLine = generatorState.repo.templates.get(sourcePath).raw[pass1[i].codeReference.lineNumber - 1];
output("raw", `// ${paddedLineNumber} | ${sourceLine}\n`);
}
if (line === "") {
if (i === pass1.length - 1) {
// If this is the last line and it's empty, we can skip it
continue;
}
if (previousLineWasEmpty) {
// If we are ignoring empty lines, skip this line
continue;
}
// When previous line was not empty, will output the current empty line but reset the flag
previousLineWasEmpty = true;
}
else {
previousLineWasEmpty = false;
}
if (line.startsWith("#")) {
if (line.startsWith("#use ")) {
const uses = line
.slice(5)
.split(" ")
.filter((s) => s.trim())
.map((s) => s.trim());
for (const use of uses) {
const pattern = lookupPattern(use);
if (!pattern) {
throw new WgslTemplateGenerateError(`Unknown use: ${use} at line ${currentLine + 1}`, "code-pattern-not-found", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
patterns.push(pattern);
}
}
else if (line.startsWith("#param ")) {
const params = line
.slice(7)
.split(" ")
.filter((s) => s.trim())
.map((s) => s.trim());
// Check if no parameters were provided
if (params.length === 0) {
throw new WgslTemplateGenerateError(`No parameters specified in #param directive at line ${currentLine + 1}`, "parameter-missing", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
for (const param of params) {
const pattern = createParamPattern(param);
if (patterns.filter((p) => p.type === "param").some((p) => p.pattern.toString() === pattern.pattern.toString())) {
throw new WgslTemplateGenerateError(`Duplicate param: ${param} at line ${currentLine + 1}`, "parameter-type-mismatch", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
patterns.push(pattern);
}
}
else if (line.startsWith("#if ")) {
if (currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`Preprocessor directive inside function call at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
// Check if there's a condition after #if
const condition = line.slice(4).trim();
if (condition.length === 0) {
throw new WgslTemplateGenerateError(`Empty condition in #if directive at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
currentColumn = 4;
preprocessIfStack.push(["if", currentParenthesesState, currentBracketState, null, null]);
output("raw", "if (");
currentPreProcessorExpression = [];
const cachedParenthesesState = currentParenthesesState;
currentParenthesesState = 0; // Reset parentheses state for preprocessor expressions
processCurrentLine();
if (currentParenthesesState !== 0) {
throw new WgslTemplateGenerateError(`Unmatched parentheses in preprocessor expression at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
currentParenthesesState = cachedParenthesesState; // Restore parentheses state
if (currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`Incomplete function call at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
generatorState.result.push(...currentPreProcessorExpression);
currentPreProcessorExpression = null;
output("raw", ") {\n");
}
else if (line.startsWith("#elif ")) {
if (preprocessIfStack.length === 0 ||
(preprocessIfStack[preprocessIfStack.length - 1][0] !== "if" &&
preprocessIfStack[preprocessIfStack.length - 1][0] !== "elif")) {
throw new WgslTemplateGenerateError(`#elif mismatch at line ${currentLine + 1}`, "code-generation-failed", {
lineNumber: currentLine + 1,
});
}
if (currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`Preprocessor directive inside function call at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
// check parentheses and brackets state
const previousBlockParenthesesState = preprocessIfStack[preprocessIfStack.length - 1][3];
if (previousBlockParenthesesState !== null && currentParenthesesState !== previousBlockParenthesesState) {
throw new WgslTemplateGenerateError(`Parentheses state mismatch in #elif directive at line ${currentLine + 1}, expected ${previousBlockParenthesesState}, got ${currentParenthesesState}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
const previousBlockBracketState = preprocessIfStack[preprocessIfStack.length - 1][4];
if (previousBlockBracketState !== null && currentBracketState !== previousBlockBracketState) {
throw new WgslTemplateGenerateError(`Bracket state mismatch in #elif directive at line ${currentLine + 1}, expected ${previousBlockBracketState}, got ${currentBracketState}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
preprocessIfStack[preprocessIfStack.length - 1][3] = currentParenthesesState; // Update the parentheses state for the current block
preprocessIfStack[preprocessIfStack.length - 1][4] = currentBracketState; // Update the bracket state for the current block
currentParenthesesState = preprocessIfStack[preprocessIfStack.length - 1][1]; // Reset parentheses state to the initial state of the current block
currentBracketState = preprocessIfStack[preprocessIfStack.length - 1][2]; // Reset bracket state to the initial state of the current block
// Check if there's a condition after #elif
const condition = line.slice(6).trim();
if (condition.length === 0) {
throw new WgslTemplateGenerateError(`Empty condition in #elif directive at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
currentColumn = 6;
preprocessIfStack[preprocessIfStack.length - 1][0] = "elif";
output("raw", "} else if (");
currentPreProcessorExpression = [];
const cachedParenthesesState = currentParenthesesState;
currentParenthesesState = 0; // Reset parentheses state for preprocessor expressions
processCurrentLine();
if (currentParenthesesState !== 0) {
throw new WgslTemplateGenerateError(`Unmatched parentheses in preprocessor expression at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
currentParenthesesState = cachedParenthesesState; // Restore parentheses state
if (currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`Incomplete function call at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
generatorState.result.push(...currentPreProcessorExpression);
currentPreProcessorExpression = null;
output("raw", ") {\n");
}
else if (line.startsWith("#else")) {
if (preprocessIfStack.length === 0 ||
(preprocessIfStack[preprocessIfStack.length - 1][0] !== "if" &&
preprocessIfStack[preprocessIfStack.length - 1][0] !== "elif")) {
throw new WgslTemplateGenerateError(`#else mismatch at line ${currentLine + 1}`, "code-generation-failed", {
lineNumber: currentLine + 1,
});
}
if (currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`Preprocessor directive inside function call at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
// check parentheses and brackets state
const previousBlockParenthesesState = preprocessIfStack[preprocessIfStack.length - 1][3];
if (previousBlockParenthesesState !== null && currentParenthesesState !== previousBlockParenthesesState) {
throw new WgslTemplateGenerateError(`Parentheses state mismatch in #elif directive at line ${currentLine + 1}, expected ${previousBlockParenthesesState}, got ${currentParenthesesState}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
const previousBlockBracketState = preprocessIfStack[preprocessIfStack.length - 1][4];
if (previousBlockBracketState !== null && currentBracketState !== previousBlockBracketState) {
throw new WgslTemplateGenerateError(`Bracket state mismatch in #elif directive at line ${currentLine + 1}, expected ${previousBlockBracketState}, got ${currentBracketState}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
preprocessIfStack[preprocessIfStack.length - 1][3] = currentParenthesesState; // Update the parentheses state for the current block
preprocessIfStack[preprocessIfStack.length - 1][4] = currentBracketState; // Update the bracket state for the current block
currentParenthesesState = preprocessIfStack[preprocessIfStack.length - 1][1]; // Reset parentheses state to the initial state of the current block
currentBracketState = preprocessIfStack[preprocessIfStack.length - 1][2]; // Reset bracket state to the initial state of the current block
if (line.substring(5).trim() !== "") {
throw new WgslTemplateGenerateError(`Unexpected content after #else at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
preprocessIfStack[preprocessIfStack.length - 1][0] = "else";
output("raw", "} else {\n");
}
else if (line.startsWith("#endif")) {
if (preprocessIfStack.length === 0) {
throw new WgslTemplateGenerateError(`#endif mismatch at line ${currentLine + 1}`, "code-generation-failed", {
lineNumber: currentLine + 1,
});
}
if (currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`Preprocessor directive inside function call at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
// check parentheses and brackets state
const previousBlockParenthesesState = preprocessIfStack[preprocessIfStack.length - 1][3];
if (previousBlockParenthesesState !== null && currentParenthesesState !== previousBlockParenthesesState) {
throw new WgslTemplateGenerateError(`Parentheses state mismatch in #elif directive at line ${currentLine + 1}, expected ${previousBlockParenthesesState}, got ${currentParenthesesState}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
const previousBlockBracketState = preprocessIfStack[preprocessIfStack.length - 1][4];
if (previousBlockBracketState !== null && currentBracketState !== previousBlockBracketState) {
throw new WgslTemplateGenerateError(`Bracket state mismatch in #elif directive at line ${currentLine + 1}, expected ${previousBlockBracketState}, got ${currentBracketState}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
if (line.substring(6).trim() !== "") {
throw new WgslTemplateGenerateError(`Unexpected content after #endif at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
output("raw", "}\n");
preprocessIfStack.pop();
}
else {
if (["#use", "#param", "#if", "#elif"].includes(line)) {
throw new WgslTemplateGenerateError(`Missing content after preprocessor directive at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
else {
// Handle unknown preprocessor directive
throw new WgslTemplateGenerateError(`Unknown preprocessor directive: ${line} at line ${currentLine + 1}`, "code-generation-failed", { filePath: generatorState.filePath, lineNumber: currentLine + 1 });
}
}
previousLineWasEmpty = true; // Reset the empty line flag after processing a preprocessor directive
}
else {
processCurrentLine();
}
}
}
const generate = (filePath, repo, codeGenerator, options) => {
const pass1 = repo.templates.get(filePath)?.pass1;
if (!pass1) {
throw new WgslTemplateGenerateError(`Template not found for file: ${filePath}`, "generator-not-found", {
filePath,
});
}
const generatorState = {
repo,
pass1,
codeGenerator,
filePath,
currentLine: 0,
currentColumn: 0,
preprocessIfStack: [],
patterns: [...DEFAULT_PATTERNS],
currentFunctionCall: [],
currentParenthesesState: 0,
mainFunction: "not-started",
currentBracketState: 0,
result: [],
usedParams: new Map(),
usedVariables: new Map(),
};
generateImpl(generatorState, options || {});
if (generatorState.preprocessIfStack.length > 0) {
throw new WgslTemplateGenerateError(`Unclosed preprocessor directive: ${generatorState.preprocessIfStack.join(", ")}`, "code-generation-failed");
}
if (generatorState.currentFunctionCall.length > 0) {
throw new WgslTemplateGenerateError(`Unclosed function call: ${generatorState.currentFunctionCall.map((call) => call.name).join(", ")}`, "code-generation-failed");
}
if (generatorState.currentParenthesesState !== 0) {
throw new WgslTemplateGenerateError(`Unmatched parentheses at the end of processing`, "code-generation-failed");
}
if (generatorState.currentBracketState !== 0) {
throw new WgslTemplateGenerateError(`Unmatched brackets at the end of processing`, "code-generation-failed");
}
if (generatorState.mainFunction === "started") {
throw new WgslTemplateGenerateError(`Main function context started but not ended at the end of processing`, "code-generation-failed");
}
// merge results
// if 2 segments are "raw" or "code" and they are adjacent, merge them into one segment
generatorState.result = mergeAdjacentSegments(generatorState.result);
// Sort params and variables by keys before returning
const sortedParamKeys = Array.from(generatorState.usedParams.keys()).sort();
const sortedVariableKeys = Array.from(generatorState.usedVariables.keys()).sort();
const sortedParams = new Map(sortedParamKeys.map((key) => [key, generatorState.usedParams.get(key)]));
const sortedVariables = new Map(sortedVariableKeys.map((key) => [key, generatorState.usedVariables.get(key)]));
return {
code: codeGenerator.emit(generatorState.result),
params: sortedParams,
variables: sortedVariables,
hasMainFunction: generatorState.mainFunction === "ended",
};
};
export const generator = {
generate,
generateDirectory(repo, codeGenerator, options) {
const result = new Map();
for (const [filePath, template] of repo.templates) {
const generateResult = generate(filePath, repo, codeGenerator, options);
result.set(filePath, {
filePath: template.filePath,
generateResult,
});
}
return {
basePath: repo.basePath,
templates: result,
};
},
};
//# sourceMappingURL=generator-impl.js.map