Skip to content

Commit 95c30a1

Browse files
authored
add a new flag preserveCodeReference (#5)
1 parent 3d4fc9f commit 95c30a1

File tree

10 files changed

+88
-10
lines changed

10 files changed

+88
-10
lines changed

bin/cli.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ Options:
295295
Available: "dynamic", "static-cpp", "static-cpp-literal"
296296
--ext <extension> Template file extension (default: ".wgsl.template")
297297
--include-prefix, -I <prefix> Include path prefix for generated headers
298+
--preserve-code-ref Preserve code references in generated output
298299
--clean, -c Clean output directory before building
299300
--debug, -d Enable debug output for detailed error information
300301
--help, -h Show this help message
@@ -335,7 +336,7 @@ async function main() {
335336
d: "debug",
336337
},
337338
string: ["input", "output", "generator", "ext", "include-prefix"],
338-
boolean: ["help", "version", "clean", "debug"],
339+
boolean: ["help", "version", "clean", "debug", "preserve-code-ref"],
339340
});
340341

341342
const options = {
@@ -346,6 +347,7 @@ async function main() {
346347
generator: argv.generator,
347348
ext: argv.ext,
348349
includePrefix: argv["include-prefix"],
350+
preserveCodeRef: argv["preserve-code-ref"],
349351
clean: argv.clean,
350352
debug: argv.debug,
351353
};
@@ -422,6 +424,9 @@ async function main() {
422424
if (options.includePrefix) {
423425
console.log(` Include prefix: ${options.includePrefix}`);
424426
}
427+
if (options.preserveCodeRef) {
428+
console.log(` Preserve code references: enabled`);
429+
}
425430
if (options.clean) {
426431
console.log(` Clean directory: enabled`);
427432
}
@@ -436,6 +441,7 @@ async function main() {
436441
templateExt,
437442
generator,
438443
includePathPrefix: options.includePrefix,
444+
preserveCodeReference: options.preserveCodeRef,
439445
});
440446

441447
// Calculate generation time

src/generator-impl.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
TemplateRepository,
1313
TemplatePass2,
1414
TemplatePass1,
15+
GenerateOptions,
1516
} from "./types.js";
1617

1718
interface FunctionCallState {
@@ -113,7 +114,7 @@ function matchNextPattern(
113114
return earliestMatch;
114115
}
115116

116-
function generateImpl(generatorState: GeneratorState) {
117+
function generateImpl(generatorState: GeneratorState, options: GenerateOptions) {
117118
const { pass1, codeGenerator, preprocessIfStack, patterns, currentFunctionCall } = generatorState;
118119

119120
let currentLine = generatorState.currentLine;
@@ -382,6 +383,13 @@ function generateImpl(generatorState: GeneratorState) {
382383
output("code", "\n");
383384
};
384385

386+
if (options.preserveCodeReference) {
387+
const maxLineNumber = pass1.length;
388+
const lineNumberWidth = String(maxLineNumber).length;
389+
const paddedLineNumber = String(currentLine + 1).padStart(lineNumberWidth, " ");
390+
output("raw", `// ${paddedLineNumber} | ${line}\n`);
391+
}
392+
385393
if (line.startsWith("#")) {
386394
if (line.startsWith("#use ")) {
387395
const uses = line
@@ -663,7 +671,8 @@ function generateImpl(generatorState: GeneratorState) {
663671
const generate = (
664672
filePath: string,
665673
repo: TemplateRepository<TemplatePass1>,
666-
codeGenerator: CodeGenerator
674+
codeGenerator: CodeGenerator,
675+
options?: GenerateOptions
667676
): GenerateResult => {
668677
const pass1 = repo.templates.get(filePath)?.pass1;
669678
if (!pass1) {
@@ -689,7 +698,7 @@ const generate = (
689698
usedVariables: new Map(),
690699
};
691700

692-
generateImpl(generatorState);
701+
generateImpl(generatorState, options || {});
693702

694703
if (generatorState.preprocessIfStack.length > 0) {
695704
throw new WgslTemplateGenerateError(
@@ -738,11 +747,11 @@ const generate = (
738747
export const generator: Generator = {
739748
generate,
740749

741-
generateDirectory(repo, codeGenerator): TemplateRepository<TemplatePass2> {
750+
generateDirectory(repo, codeGenerator, options): TemplateRepository<TemplatePass2> {
742751
const result = new Map<string, TemplatePass2>();
743752

744753
for (const [filePath, template] of repo.templates) {
745-
const generateResult = generate(filePath, repo, codeGenerator);
754+
const generateResult = generate(filePath, repo, codeGenerator, options);
746755
result.set(filePath, {
747756
filePath: template.filePath,
748757
generateResult,

src/index.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ export interface BuildOptions {
4242
* `#include "myproject/a/b/shader.wgsl"`
4343
*/
4444
includePathPrefix?: string;
45+
46+
/**
47+
* Whether to preserve code references in the generated output.
48+
*
49+
* If true, comments will be added to the generated code indicating the original template file and line number.
50+
* This can be useful for debugging and tracing back to the source templates.
51+
*
52+
* Default is false.
53+
*/
54+
preserveCodeReference?: boolean;
4555
}
4656

4757
/**
@@ -80,7 +90,9 @@ export const build = async (options: BuildOptions): Promise<BuildResult> => {
8090
pass1 = parser.parse(pass0);
8191

8292
const codeGenerator = resolveCodeGenerator(options.generator);
83-
pass2 = generator.generateDirectory(pass1, codeGenerator);
93+
pass2 = generator.generateDirectory(pass1, codeGenerator, {
94+
preserveCodeReference: options.preserveCodeReference,
95+
});
8496

8597
const files = codeGenerator.build(pass2, {
8698
templateExt: options.templateExt,

src/types.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ export interface CodePattern {
132132
// Generator Types
133133
// ============================================================================
134134

135+
export interface GenerateOptions {
136+
preserveCodeReference?: boolean;
137+
}
138+
135139
export interface GenerateResult {
136140
code: string;
137141
params: Map<string, NonNullable<CodePattern["paramType"]>>; // name -> type
@@ -140,11 +144,17 @@ export interface GenerateResult {
140144
}
141145

142146
export interface Generator {
143-
generate(filePath: string, repo: TemplateRepository<TemplatePass1>, generator: CodeGenerator): GenerateResult;
147+
generate(
148+
filePath: string,
149+
repo: TemplateRepository<TemplatePass1>,
150+
generator: CodeGenerator,
151+
options?: GenerateOptions
152+
): GenerateResult;
144153

145154
generateDirectory(
146155
repo: TemplateRepository<TemplatePass1>,
147-
generator: CodeGenerator
156+
generator: CodeGenerator,
157+
options?: GenerateOptions
148158
): TemplateRepository<TemplatePass2>;
149159
}
150160

test/test-runner-generator.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ export async function runGeneratorTest(testCase: TestCase, debug?: boolean): Pro
8888

8989
try {
9090
// Generate the actual output
91-
const generateResult = generator.generate(entryConfig.templatePath, parsedRepo, codeGenerator);
91+
const generateResult = generator.generate(entryConfig.templatePath, parsedRepo, codeGenerator, {
92+
preserveCodeReference: config.preserveCodeReference,
93+
});
9294
const actualOutput = generateResult.code;
9395

9496
// If we expected an error but got here without throwing, that's a failure

test/test-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export interface BuildTestConfig extends BaseTestConfig {
4646
// Generator test configuration
4747
export interface GeneratorTestConfig extends BaseTestConfig {
4848
type: "generator";
49+
preserveCodeReference?: boolean; // Whether to preserve code references in generated output
4950
// Generator tests use object with template file paths as keys
5051
entries: Record<
5152
string,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"type": "generator",
3+
"description": "Basic generator test with preserveCodeReference enabled",
4+
"preserveCodeReference": true,
5+
"entries": {
6+
"test.wgsl.template": {
7+
"generators": {
8+
"dynamic": {},
9+
"static-cpp-literal": {}
10+
}
11+
}
12+
}
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@compute @workgroup_size(128)
2+
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
3+
let buffer_count = 4;
4+
let index = global_id.x;
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// 1 | @compute @workgroup_size(128)
2+
emit("@compute @workgroup_size(128)\n");
3+
// 2 | fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
4+
emit("fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {\n");
5+
// 3 | let buffer_count = 4;
6+
emit(" let buffer_count = 4;\n");
7+
// 4 | let index = global_id.x;
8+
emit(" let index = global_id.x;\n");
9+
// 5 | }
10+
emit("}\n");
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// 1 | @compute @workgroup_size(128)
2+
(*ss_ptr) << "@compute @workgroup_size(128)\n";
3+
// 2 | fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
4+
(*ss_ptr) << "fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {\n";
5+
// 3 | let buffer_count = 4;
6+
(*ss_ptr) << " let buffer_count = 4;\n";
7+
// 4 | let index = global_id.x;
8+
(*ss_ptr) << " let index = global_id.x;\n";
9+
// 5 | }
10+
(*ss_ptr) << "}\n";

0 commit comments

Comments
 (0)