@gasm-compiler/cli 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +3 -0
  2. package/dist/cli.js +89 -15
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -4,6 +4,9 @@
4
4
 
5
5
  Compile WebAssembly (`.wasm`) or AssemblyScript (`.as`/`.ts`) files to WGSL compute shaders from the command line. Built on top of [`@gasm-compiler/core`](https://www.npmjs.com/package/@gasm-compiler/core).
6
6
 
7
+ Version 0.2 defaults to strict Gasm v0.2 compilation. Use
8
+ `--spec-version 0.1` only for archived v0.1 inputs.
9
+
7
10
  ---
8
11
 
9
12
  ## Installation
package/dist/cli.js CHANGED
@@ -9,10 +9,12 @@ import { parseArgs } from "jsr:@std/cli/parse-args";
9
9
  import { resolve } from "jsr:@std/path";
10
10
  import { ensureFile } from "jsr:@std/fs";
11
11
  import {
12
+ compileToArtifact,
12
13
  compileWithDiagnostics,
13
14
  disassembleToWAT,
15
+ isParseError,
14
16
  parseWasmModule,
15
- isParseError
17
+ validateGasmMetadataSchema
16
18
  } from "@gasm-compiler/core";
17
19
  function printDiagnostics(diagnostics, verbose) {
18
20
  for (const w of diagnostics.warnings) {
@@ -24,13 +26,17 @@ function printDiagnostics(diagnostics, verbose) {
24
26
  for (const d of diagnostics.demotions) {
25
27
  counts.set(d.kind, (counts.get(d.kind) ?? 0) + 1);
26
28
  }
27
- const parts = [...counts.entries()].map(([kind, count]) => `${kind} (${count})`);
29
+ const parts = [...counts.entries()].map(
30
+ ([kind, count]) => `${kind} (${count})`
31
+ );
28
32
  console.error(`demotions: ${parts.join(", ")}`);
29
33
  }
30
34
  }
31
35
  async function compileAssemblyScriptToWGSL(inputFile, options = {}) {
32
36
  const {
33
37
  output: outputFile,
38
+ metadata: metadataFile,
39
+ specVersion: requestedSpecVersion,
34
40
  watOutput: watOutputFile,
35
41
  verbose = false,
36
42
  keepWasm = false,
@@ -41,6 +47,17 @@ async function compileAssemblyScriptToWGSL(inputFile, options = {}) {
41
47
  sourceMapping
42
48
  } = options;
43
49
  try {
50
+ if (requestedSpecVersion !== void 0 && requestedSpecVersion !== "0.1" && requestedSpecVersion !== "0.2") {
51
+ throw new Error(
52
+ `Unsupported spec version "${requestedSpecVersion}"; expected 0.1 or 0.2`
53
+ );
54
+ }
55
+ const specVersion = requestedSpecVersion ?? "0.2";
56
+ if (metadataFile && specVersion !== "0.2") {
57
+ throw new Error(
58
+ "--metadata requires --spec-version 0.2"
59
+ );
60
+ }
44
61
  if (verbose) console.log(`[1/4] Validating input file: ${inputFile}`);
45
62
  const resolvedInput = resolve(inputFile);
46
63
  const stats = await Deno.stat(resolvedInput);
@@ -49,7 +66,9 @@ async function compileAssemblyScriptToWGSL(inputFile, options = {}) {
49
66
  }
50
67
  const isWasm = resolvedInput.endsWith(".wasm");
51
68
  if (!isWasm && !resolvedInput.endsWith(".as") && !resolvedInput.endsWith(".ts")) {
52
- console.warn("Warning: Input file does not have .as, .ts, or .wasm extension");
69
+ console.warn(
70
+ "Warning: Input file does not have .as, .ts, or .wasm extension"
71
+ );
53
72
  }
54
73
  let wasmPath = resolvedInput.replace(/\.(as|ts)$/, ".wasm");
55
74
  if (!isWasm) {
@@ -104,28 +123,63 @@ ${errorMsg}`);
104
123
  const demotionPolicy = {};
105
124
  if (denyF64Demotion) demotionPolicy.f64 = "deny";
106
125
  if (allowI64Demotion) demotionPolicy.i64 = "allow-lossy";
107
- const validLevels = ["none", "minimal", "normal", "detailed", "verbose"];
126
+ const validLevels = [
127
+ "none",
128
+ "minimal",
129
+ "normal",
130
+ "detailed",
131
+ "verbose"
132
+ ];
108
133
  let sourceMappingLevel;
109
134
  if (sourceMapping) {
110
135
  if (validLevels.includes(sourceMapping)) {
111
136
  sourceMappingLevel = sourceMapping;
112
137
  } else {
113
- console.warn(`Warning: Unknown source-mapping level "${sourceMapping}", using "normal"`);
138
+ console.warn(
139
+ `Warning: Unknown source-mapping level "${sourceMapping}", using "normal"`
140
+ );
114
141
  sourceMappingLevel = "normal";
115
142
  }
116
143
  }
117
- const result = compileWithDiagnostics(wasmBytes, {
144
+ const compileOptions = {
118
145
  optimize,
119
146
  demotionPolicy,
120
147
  warningsAsErrors,
121
- sourceMapping: sourceMappingLevel
122
- });
148
+ sourceMapping: sourceMappingLevel,
149
+ specVersion
150
+ };
151
+ const result = metadataFile ? compileToArtifact(wasmBytes, compileOptions) : compileWithDiagnostics(wasmBytes, compileOptions);
123
152
  printDiagnostics(result.diagnostics, verbose);
124
153
  if (!result.ok) {
125
154
  const first = result.diagnostics.errors[0];
126
- throw new Error(first?.message ?? "Compilation failed");
155
+ throw new Error(
156
+ first ? `${first.code}: ${first.message}` : "Compilation failed"
157
+ );
127
158
  }
128
159
  const wgslCode = result.wgsl;
160
+ if (metadataFile) {
161
+ if (!("metadata" in result)) {
162
+ throw new Error("Compiler did not produce metadata");
163
+ }
164
+ const schema = validateGasmMetadataSchema(result.metadata);
165
+ if (!schema.valid) {
166
+ throw new Error(
167
+ `Generated metadata failed schema validation: ${schema.errors.join(", ")}`
168
+ );
169
+ }
170
+ const resolvedMetadata = resolve(metadataFile);
171
+ await ensureFile(resolvedMetadata);
172
+ await Deno.writeTextFile(
173
+ resolvedMetadata,
174
+ `${JSON.stringify(result.metadata, null, 2)}
175
+ `
176
+ );
177
+ if (verbose) {
178
+ console.log(`\u2713 Metadata written to: ${resolvedMetadata}`);
179
+ } else {
180
+ console.log(`\u2713 Metadata written to: ${metadataFile}`);
181
+ }
182
+ }
129
183
  if (watOutputFile) {
130
184
  if (verbose) console.log("[4a/4] Generating WAT disassembly...");
131
185
  const parseResult = parseWasmModule(wasmBytes);
@@ -140,7 +194,9 @@ ${errorMsg}`);
140
194
  console.log(`\u2713 WAT written to: ${watOutputFile}`);
141
195
  }
142
196
  } else {
143
- console.warn(`Warning: Failed to parse WASM for WAT disassembly: ${parseResult.message}`);
197
+ console.warn(
198
+ `Warning: Failed to parse WASM for WAT disassembly: ${parseResult.message}`
199
+ );
144
200
  }
145
201
  }
146
202
  if (outputFile) {
@@ -174,7 +230,10 @@ async function getAssemblyScriptPath() {
174
230
  const possiblePaths = [
175
231
  // Relative to CLI package
176
232
  resolve(scriptDir, "../../node_modules/.bin/asc"),
177
- resolve(scriptDir, "../../node_modules/.pnpm/assemblyscript@0.28.9/node_modules/assemblyscript/node_modules/.bin/asc"),
233
+ resolve(
234
+ scriptDir,
235
+ "../../node_modules/.pnpm/assemblyscript@0.28.9/node_modules/assemblyscript/node_modules/.bin/asc"
236
+ ),
178
237
  resolve(scriptDir, "../node_modules/.bin/asc"),
179
238
  resolve(scriptDir, "../examples/node_modules/.bin/asc"),
180
239
  // Relative to workspace root
@@ -196,10 +255,16 @@ async function getAssemblyScriptPath() {
196
255
  }
197
256
 
198
257
  // src/cli.ts
199
- var VERSION = "0.1.0";
258
+ var VERSION = "0.2.0";
200
259
  async function main() {
201
260
  const args = parseArgs(Deno.args, {
202
- string: ["output", "wat-output", "source-mapping"],
261
+ string: [
262
+ "output",
263
+ "metadata",
264
+ "spec-version",
265
+ "wat-output",
266
+ "source-mapping"
267
+ ],
203
268
  boolean: [
204
269
  "help",
205
270
  "version",
@@ -229,12 +294,16 @@ async function main() {
229
294
  if (command === "compile") {
230
295
  if (args._.length < 2) {
231
296
  console.error("Error: compile requires an input file");
232
- console.error("Usage: cli compile <input.as|wasm> [--output <output.wgsl>]");
297
+ console.error(
298
+ "Usage: cli compile <input.as|wasm> [--output <output.wgsl>]"
299
+ );
233
300
  Deno.exit(1);
234
301
  }
235
302
  const inputFile = args._[1];
236
303
  const options = {
237
304
  output: args.output,
305
+ metadata: args.metadata,
306
+ specVersion: args["spec-version"],
238
307
  watOutput: args["wat-output"],
239
308
  verbose: args.verbose,
240
309
  keepWasm: args["keep-wasm"],
@@ -251,7 +320,10 @@ async function main() {
251
320
  Deno.exit(1);
252
321
  }
253
322
  } catch (error) {
254
- console.error("Error:", error instanceof Error ? error.message : String(error));
323
+ console.error(
324
+ "Error:",
325
+ error instanceof Error ? error.message : String(error)
326
+ );
255
327
  if (args.verbose && error instanceof Error && error.stack) {
256
328
  console.error("\nStack trace:");
257
329
  console.error(error.stack);
@@ -274,6 +346,8 @@ COMMANDS:
274
346
 
275
347
  OPTIONS:
276
348
  --output <file> Write WGSL output to file (default: stdout)
349
+ --metadata <file> Write validated Gasm v0.2 metadata sidecar JSON
350
+ --spec-version <version> Compile as Gasm 0.1 or 0.2 (default: 0.2)
277
351
  --wat-output <file> Also write WAT (WebAssembly Text) disassembly to file
278
352
  --verbose Show detailed compilation steps
279
353
  --keep-wasm Keep intermediate WASM files
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gasm-compiler/cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "CLI for compiling WebAssembly/AssemblyScript to WGSL using Gasm Compiler",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",
@@ -35,7 +35,7 @@
35
35
  "cli"
36
36
  ],
37
37
  "dependencies": {
38
- "@gasm-compiler/core": "0.1.1"
38
+ "@gasm-compiler/core": "0.4.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "assemblyscript": "v0.28.9",