wesl-link 0.6.15 → 0.6.16

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 (2) hide show
  1. package/bin/wesl-link +182 -1525
  2. package/package.json +3 -3
package/bin/wesl-link CHANGED
@@ -3,11 +3,11 @@ import { hideBin } from "yargs/helpers";
3
3
  import path, { posix, win32 } from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import { resolve } from "import-meta-resolve";
6
- import { CachingStream, MatchersStream, ParseError, RegexMatchers, collectArray, delimited, enableTracing, eof, fn, kind, log, matchOneOf, not, opt, or, preceded, repeat, repeatPlus, req, separated_pair, seq, seqObj, span, tagScope, terminated, text, token, tokenKind, tokenOf, tracing, withSep, withSepPlus, withStreamAction, yes } from "mini-parse";
7
- import { WeslParseError, astToString, filterMap, findUnboundIdents, link, parseIntoRegistry, parsedRegistry, scopeToString } from "wesl";
6
+ import { enableTracing, log } from "mini-parse";
7
+ import { RecordResolver, WeslParseError, astToString, bindIdentsRecursive, filterMap, findValidRootDecls, link, minimalMangle, scopeToString } from "wesl";
8
+ import * as actualFS from "node:fs";
8
9
  import fs, { lstat, readdir, readlink, realpath } from "node:fs/promises";
9
10
  import { lstatSync, readdir as readdir$1, readdirSync, readlinkSync, realpathSync } from "fs";
10
- import * as actualFS from "node:fs";
11
11
  import { EventEmitter } from "node:events";
12
12
  import Stream from "node:stream";
13
13
  import { StringDecoder } from "node:string_decoder";
@@ -38,6 +38,41 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
38
38
  enumerable: true
39
39
  }) : target, mod));
40
40
 
41
+ //#endregion
42
+ //#region ../wesl-tooling/src/FindUnboundIdents.ts
43
+ /**
44
+ * Find unbound package references in library sources.
45
+ *
46
+ * Binds local references without following cross-package imports, revealing
47
+ * which external packages are referenced but not resolved.
48
+ *
49
+ * @param resolver - Module resolver that supports batch operations
50
+ * @returns Array of unbound module paths, each as an array of path segments
51
+ * (e.g., [['foo', 'bar', 'baz'], ['other', 'pkg']])
52
+ */
53
+ function findUnboundIdents(resolver) {
54
+ const bindContext = {
55
+ resolver,
56
+ conditions: {},
57
+ knownDecls: /* @__PURE__ */ new Set(),
58
+ foundScopes: /* @__PURE__ */ new Set(),
59
+ globalNames: /* @__PURE__ */ new Set(),
60
+ globalStatements: /* @__PURE__ */ new Map(),
61
+ mangler: minimalMangle,
62
+ unbound: [],
63
+ dontFollowDecls: true
64
+ };
65
+ for (const [_modulePath, ast] of resolver.allModules()) {
66
+ const declEntries = findValidRootDecls(ast.rootScope, {}).map((d) => [d.originalName, d]);
67
+ const liveDecls = {
68
+ decls: new Map(declEntries),
69
+ parent: null
70
+ };
71
+ bindIdentsRecursive(ast.rootScope, bindContext, liveDecls, true);
72
+ }
73
+ return bindContext.unbound;
74
+ }
75
+
41
76
  //#endregion
42
77
  //#region ../../node_modules/.pnpm/@isaacs+balanced-match@4.0.1/node_modules/@isaacs/balanced-match/dist/esm/index.js
43
78
  const balanced = (a, b, str) => {
@@ -373,7 +408,7 @@ const parseClass = (glob$1, position) => {
373
408
  * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
374
409
  * or unescaped.
375
410
  */
376
- const unescape$1 = (s, { windowsPathsNoEscape = false } = {}) => {
411
+ const unescape = (s, { windowsPathsNoEscape = false } = {}) => {
377
412
  return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1");
378
413
  };
379
414
 
@@ -504,7 +539,7 @@ var AST = class AST {
504
539
  for (const p of this.#parts) c.copyIn(p);
505
540
  return c;
506
541
  }
507
- static #parseAST(str, ast, pos, opt$1) {
542
+ static #parseAST(str, ast, pos, opt) {
508
543
  let escaping = false;
509
544
  let inBrace = false;
510
545
  let braceStart = -1;
@@ -532,11 +567,11 @@ var AST = class AST {
532
567
  acc$1 += c;
533
568
  continue;
534
569
  }
535
- if (!opt$1.noext && isExtglobType(c) && str.charAt(i$1) === "(") {
570
+ if (!opt.noext && isExtglobType(c) && str.charAt(i$1) === "(") {
536
571
  ast.push(acc$1);
537
572
  acc$1 = "";
538
573
  const ext$1 = new AST(c, ast);
539
- i$1 = AST.#parseAST(str, ext$1, i$1, opt$1);
574
+ i$1 = AST.#parseAST(str, ext$1, i$1, opt);
540
575
  ast.push(ext$1);
541
576
  continue;
542
577
  }
@@ -574,7 +609,7 @@ var AST = class AST {
574
609
  acc = "";
575
610
  const ext$1 = new AST(c, part);
576
611
  part.push(ext$1);
577
- i = AST.#parseAST(str, ext$1, i, opt$1);
612
+ i = AST.#parseAST(str, ext$1, i, opt);
578
613
  continue;
579
614
  }
580
615
  if (c === "|") {
@@ -645,7 +680,7 @@ var AST = class AST {
645
680
  if (this.isEnd() && this.#root.#filledNegs && this.#parent?.type === "!") end = "(?:$|\\/)";
646
681
  return [
647
682
  start$1 + src + end,
648
- unescape$1(src),
683
+ unescape(src),
649
684
  this.#hasMagic = !!this.#hasMagic,
650
685
  this.#uflag
651
686
  ];
@@ -660,7 +695,7 @@ var AST = class AST {
660
695
  this.#hasMagic = void 0;
661
696
  return [
662
697
  s,
663
- unescape$1(this.toString()),
698
+ unescape(this.toString()),
664
699
  false,
665
700
  false
666
701
  ];
@@ -676,7 +711,7 @@ var AST = class AST {
676
711
  }
677
712
  return [
678
713
  final,
679
- unescape$1(body),
714
+ unescape(body),
680
715
  this.#hasMagic = !!this.#hasMagic,
681
716
  this.#uflag
682
717
  ];
@@ -732,7 +767,7 @@ var AST = class AST {
732
767
  }
733
768
  return [
734
769
  re,
735
- unescape$1(glob$1),
770
+ unescape(glob$1),
736
771
  !!hasMagic$1,
737
772
  uflag
738
773
  ];
@@ -1319,7 +1354,7 @@ var Minimatch = class {
1319
1354
  minimatch.AST = AST;
1320
1355
  minimatch.Minimatch = Minimatch;
1321
1356
  minimatch.escape = escape;
1322
- minimatch.unescape = unescape$1;
1357
+ minimatch.unescape = unescape;
1323
1358
 
1324
1359
  //#endregion
1325
1360
  //#region ../../node_modules/.pnpm/lru-cache@11.2.2/node_modules/lru-cache/dist/esm/index.js
@@ -1331,8 +1366,8 @@ const warned = /* @__PURE__ */ new Set();
1331
1366
  /* c8 ignore start */
1332
1367
  const PROCESS = typeof process === "object" && !!process ? process : {};
1333
1368
  /* c8 ignore start */
1334
- const emitWarning = (msg, type, code, fn$1) => {
1335
- typeof PROCESS.emitWarning === "function" ? PROCESS.emitWarning(msg, type, code, fn$1) : console.error(`[${code}] ${type}: ${msg}`);
1369
+ const emitWarning = (msg, type, code, fn) => {
1370
+ typeof PROCESS.emitWarning === "function" ? PROCESS.emitWarning(msg, type, code, fn) : console.error(`[${code}] ${type}: ${msg}`);
1336
1371
  };
1337
1372
  let AC = globalThis.AbortController;
1338
1373
  let AS = globalThis.AbortSignal;
@@ -1343,8 +1378,8 @@ if (typeof AC === "undefined") {
1343
1378
  _onabort = [];
1344
1379
  reason;
1345
1380
  aborted = false;
1346
- addEventListener(_, fn$1) {
1347
- this._onabort.push(fn$1);
1381
+ addEventListener(_, fn) {
1382
+ this._onabort.push(fn);
1348
1383
  }
1349
1384
  };
1350
1385
  AC = class AbortController {
@@ -1356,7 +1391,7 @@ if (typeof AC === "undefined") {
1356
1391
  if (this.signal.aborted) return;
1357
1392
  this.signal.reason = reason;
1358
1393
  this.signal.aborted = true;
1359
- for (const fn$1 of this.signal._onabort) fn$1(reason);
1394
+ for (const fn of this.signal._onabort) fn(reason);
1360
1395
  this.signal.onabort?.(reason);
1361
1396
  }
1362
1397
  };
@@ -1869,12 +1904,12 @@ var LRUCache = class LRUCache {
1869
1904
  * Find a value for which the supplied fn method returns a truthy value,
1870
1905
  * similar to `Array.find()`. fn is called as `fn(value, key, cache)`.
1871
1906
  */
1872
- find(fn$1, getOptions = {}) {
1907
+ find(fn, getOptions = {}) {
1873
1908
  for (const i of this.#indexes()) {
1874
1909
  const v = this.#valList[i];
1875
1910
  const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
1876
1911
  if (value === void 0) continue;
1877
- if (fn$1(value, this.#keyList[i], this)) return this.get(this.#keyList[i], getOptions);
1912
+ if (fn(value, this.#keyList[i], this)) return this.get(this.#keyList[i], getOptions);
1878
1913
  }
1879
1914
  }
1880
1915
  /**
@@ -1888,24 +1923,24 @@ var LRUCache = class LRUCache {
1888
1923
  *
1889
1924
  * Does not update age or recenty of use, or iterate over stale values.
1890
1925
  */
1891
- forEach(fn$1, thisp = this) {
1926
+ forEach(fn, thisp = this) {
1892
1927
  for (const i of this.#indexes()) {
1893
1928
  const v = this.#valList[i];
1894
1929
  const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
1895
1930
  if (value === void 0) continue;
1896
- fn$1.call(thisp, value, this.#keyList[i], this);
1931
+ fn.call(thisp, value, this.#keyList[i], this);
1897
1932
  }
1898
1933
  }
1899
1934
  /**
1900
1935
  * The same as {@link LRUCache.forEach} but items are iterated over in
1901
1936
  * reverse order. (ie, less recently used items are iterated over first.)
1902
1937
  */
1903
- rforEach(fn$1, thisp = this) {
1938
+ rforEach(fn, thisp = this) {
1904
1939
  for (const i of this.#rindexes()) {
1905
1940
  const v = this.#valList[i];
1906
1941
  const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
1907
1942
  if (value === void 0) continue;
1908
- fn$1.call(thisp, value, this.#keyList[i], this);
1943
+ fn.call(thisp, value, this.#keyList[i], this);
1909
1944
  }
1910
1945
  }
1911
1946
  /**
@@ -2552,8 +2587,8 @@ const ABORTED = Symbol("aborted");
2552
2587
  const SIGNAL = Symbol("signal");
2553
2588
  const DATALISTENERS = Symbol("dataListeners");
2554
2589
  const DISCARDED = Symbol("discarded");
2555
- const defer = (fn$1) => Promise.resolve().then(fn$1);
2556
- const nodefer = (fn$1) => fn$1();
2590
+ const defer = (fn) => Promise.resolve().then(fn);
2591
+ const nodefer = (fn) => fn();
2557
2592
  const isEndish = (ev) => ev === "end" || ev === "finish" || ev === "prefinish";
2558
2593
  const isArrayBufferLike = (b) => b instanceof ArrayBuffer || !!b && typeof b === "object" && b.constructor && b.constructor.name === "ArrayBuffer" && b.byteLength >= 0;
2559
2594
  const isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b);
@@ -2760,7 +2795,7 @@ var Minipass = class extends EventEmitter {
2760
2795
  encoding = "utf8";
2761
2796
  }
2762
2797
  if (!encoding) encoding = "utf8";
2763
- const fn$1 = this[ASYNC] ? defer : nodefer;
2798
+ const fn = this[ASYNC] ? defer : nodefer;
2764
2799
  if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {
2765
2800
  if (isArrayBufferView(chunk)) chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
2766
2801
  else if (isArrayBufferLike(chunk)) chunk = Buffer.from(chunk);
@@ -2773,12 +2808,12 @@ var Minipass = class extends EventEmitter {
2773
2808
  if (this[FLOWING]) this.emit("data", chunk);
2774
2809
  else this[BUFFERPUSH](chunk);
2775
2810
  if (this[BUFFERLENGTH] !== 0) this.emit("readable");
2776
- if (cb) fn$1(cb);
2811
+ if (cb) fn(cb);
2777
2812
  return this[FLOWING];
2778
2813
  }
2779
2814
  if (!chunk.length) {
2780
2815
  if (this[BUFFERLENGTH] !== 0) this.emit("readable");
2781
- if (cb) fn$1(cb);
2816
+ if (cb) fn(cb);
2782
2817
  return this[FLOWING];
2783
2818
  }
2784
2819
  if (typeof chunk === "string" && !(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)) chunk = Buffer.from(chunk, encoding);
@@ -2787,7 +2822,7 @@ var Minipass = class extends EventEmitter {
2787
2822
  if (this[FLOWING]) this.emit("data", chunk);
2788
2823
  else this[BUFFERPUSH](chunk);
2789
2824
  if (this[BUFFERLENGTH] !== 0) this.emit("readable");
2790
- if (cb) fn$1(cb);
2825
+ if (cb) fn(cb);
2791
2826
  return this[FLOWING];
2792
2827
  }
2793
2828
  /**
@@ -3367,7 +3402,7 @@ const ENOCHILD = ENOENT | 576;
3367
3402
  const TYPEMASK = 1023;
3368
3403
  const entToType = (s) => s.isFile() ? IFREG : s.isDirectory() ? IFDIR : s.isSymbolicLink() ? IFLNK : s.isCharacterDevice() ? IFCHR : s.isBlockDevice() ? IFBLK : s.isSocket() ? IFSOCK : s.isFIFO() ? IFIFO : UNKNOWN;
3369
3404
  const normalizeCache = /* @__PURE__ */ new Map();
3370
- const normalize$1 = (s) => {
3405
+ const normalize = (s) => {
3371
3406
  const c = normalizeCache.get(s);
3372
3407
  if (c) return c;
3373
3408
  const n = s.normalize("NFKD");
@@ -3378,7 +3413,7 @@ const normalizeNocaseCache = /* @__PURE__ */ new Map();
3378
3413
  const normalizeNocase = (s) => {
3379
3414
  const c = normalizeNocaseCache.get(s);
3380
3415
  if (c) return c;
3381
- const n = normalize$1(s.toLowerCase());
3416
+ const n = normalize(s.toLowerCase());
3382
3417
  normalizeNocaseCache.set(s, n);
3383
3418
  return n;
3384
3419
  };
@@ -3563,9 +3598,9 @@ var PathBase = class {
3563
3598
  *
3564
3599
  * @internal
3565
3600
  */
3566
- constructor(name$1, type = UNKNOWN, root, roots, nocase, children, opts) {
3567
- this.name = name$1;
3568
- this.#matchName = nocase ? normalizeNocase(name$1) : normalize$1(name$1);
3601
+ constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
3602
+ this.name = name;
3603
+ this.#matchName = nocase ? normalizeNocase(name) : normalize(name);
3569
3604
  this.#type = type & TYPEMASK;
3570
3605
  this.nocase = nocase;
3571
3606
  this.roots = roots;
@@ -3641,8 +3676,8 @@ var PathBase = class {
3641
3676
  if (pathPart === "" || pathPart === ".") return this;
3642
3677
  if (pathPart === "..") return this.parent || this;
3643
3678
  const children = this.children();
3644
- const name$1 = this.nocase ? normalizeNocase(pathPart) : normalize$1(pathPart);
3645
- for (const p of children) if (p.#matchName === name$1) return p;
3679
+ const name = this.nocase ? normalizeNocase(pathPart) : normalize(pathPart);
3680
+ for (const p of children) if (p.#matchName === name) return p;
3646
3681
  const s = this.parent ? this.sep : "";
3647
3682
  const fullpath = this.#fullpath ? this.#fullpath + s + pathPart : void 0;
3648
3683
  const pchild = this.newChild(pathPart, UNKNOWN, {
@@ -3661,11 +3696,11 @@ var PathBase = class {
3661
3696
  relative() {
3662
3697
  if (this.isCWD) return "";
3663
3698
  if (this.#relative !== void 0) return this.#relative;
3664
- const name$1 = this.name;
3699
+ const name = this.name;
3665
3700
  const p = this.parent;
3666
3701
  if (!p) return this.#relative = this.name;
3667
3702
  const pv = p.relative();
3668
- return pv + (!pv || !p.parent ? "" : this.sep) + name$1;
3703
+ return pv + (!pv || !p.parent ? "" : this.sep) + name;
3669
3704
  }
3670
3705
  /**
3671
3706
  * The relative path from the cwd, using / as the path separator.
@@ -3677,21 +3712,21 @@ var PathBase = class {
3677
3712
  if (this.sep === "/") return this.relative();
3678
3713
  if (this.isCWD) return "";
3679
3714
  if (this.#relativePosix !== void 0) return this.#relativePosix;
3680
- const name$1 = this.name;
3715
+ const name = this.name;
3681
3716
  const p = this.parent;
3682
3717
  if (!p) return this.#relativePosix = this.fullpathPosix();
3683
3718
  const pv = p.relativePosix();
3684
- return pv + (!pv || !p.parent ? "" : "/") + name$1;
3719
+ return pv + (!pv || !p.parent ? "" : "/") + name;
3685
3720
  }
3686
3721
  /**
3687
3722
  * The fully resolved path string for this Path entry
3688
3723
  */
3689
3724
  fullpath() {
3690
3725
  if (this.#fullpath !== void 0) return this.#fullpath;
3691
- const name$1 = this.name;
3726
+ const name = this.name;
3692
3727
  const p = this.parent;
3693
3728
  if (!p) return this.#fullpath = this.name;
3694
- return this.#fullpath = p.fullpath() + (!p.parent ? "" : this.sep) + name$1;
3729
+ return this.#fullpath = p.fullpath() + (!p.parent ? "" : this.sep) + name;
3695
3730
  }
3696
3731
  /**
3697
3732
  * On platforms other than windows, this is identical to fullpath.
@@ -3854,7 +3889,7 @@ var PathBase = class {
3854
3889
  * directly.
3855
3890
  */
3856
3891
  isNamed(n) {
3857
- return !this.nocase ? this.#matchName === normalize$1(n) : this.#matchName === normalizeNocase(n);
3892
+ return !this.nocase ? this.#matchName === normalize(n) : this.#matchName === normalizeNocase(n);
3858
3893
  }
3859
3894
  /**
3860
3895
  * Return the Path object corresponding to the target of a symbolic link.
@@ -3966,7 +4001,7 @@ var PathBase = class {
3966
4001
  #readdirMaybePromoteChild(e, c) {
3967
4002
  for (let p = c.provisional; p < c.length; p++) {
3968
4003
  const pchild = c[p];
3969
- if ((this.nocase ? normalizeNocase(e.name) : normalize$1(e.name)) !== pchild.#matchName) continue;
4004
+ if ((this.nocase ? normalizeNocase(e.name) : normalize(e.name)) !== pchild.#matchName) continue;
3970
4005
  return this.#readdirPromoteChild(e, pchild, p, c);
3971
4006
  }
3972
4007
  }
@@ -4234,14 +4269,14 @@ var PathWin32 = class PathWin32 extends PathBase {
4234
4269
  *
4235
4270
  * @internal
4236
4271
  */
4237
- constructor(name$1, type = UNKNOWN, root, roots, nocase, children, opts) {
4238
- super(name$1, type, root, roots, nocase, children, opts);
4272
+ constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
4273
+ super(name, type, root, roots, nocase, children, opts);
4239
4274
  }
4240
4275
  /**
4241
4276
  * @internal
4242
4277
  */
4243
- newChild(name$1, type = UNKNOWN, opts = {}) {
4244
- return new PathWin32(name$1, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
4278
+ newChild(name, type = UNKNOWN, opts = {}) {
4279
+ return new PathWin32(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
4245
4280
  }
4246
4281
  /**
4247
4282
  * @internal
@@ -4286,8 +4321,8 @@ var PathPosix = class PathPosix extends PathBase {
4286
4321
  *
4287
4322
  * @internal
4288
4323
  */
4289
- constructor(name$1, type = UNKNOWN, root, roots, nocase, children, opts) {
4290
- super(name$1, type, root, roots, nocase, children, opts);
4324
+ constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
4325
+ super(name, type, root, roots, nocase, children, opts);
4291
4326
  }
4292
4327
  /**
4293
4328
  * @internal
@@ -4304,8 +4339,8 @@ var PathPosix = class PathPosix extends PathBase {
4304
4339
  /**
4305
4340
  * @internal
4306
4341
  */
4307
- newChild(name$1, type = UNKNOWN, opts = {}) {
4308
- return new PathPosix(name$1, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
4342
+ newChild(name, type = UNKNOWN, opts = {}) {
4343
+ return new PathPosix(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
4309
4344
  }
4310
4345
  };
4311
4346
  /**
@@ -5365,16 +5400,16 @@ var GlobUtil = class {
5365
5400
  if (this.signal?.aborted) return;
5366
5401
  /* c8 ignore stop */
5367
5402
  this.paused = false;
5368
- let fn$1 = void 0;
5369
- while (!this.paused && (fn$1 = this.#onResume.shift())) fn$1();
5403
+ let fn = void 0;
5404
+ while (!this.paused && (fn = this.#onResume.shift())) fn();
5370
5405
  }
5371
- onResume(fn$1) {
5406
+ onResume(fn) {
5372
5407
  if (this.signal?.aborted) return;
5373
5408
  /* c8 ignore start */
5374
- if (!this.paused) fn$1();
5409
+ if (!this.paused) fn();
5375
5410
  else
5376
5411
  /* c8 ignore stop */
5377
- this.#onResume.push(fn$1);
5412
+ this.#onResume.push(fn);
5378
5413
  }
5379
5414
  async matchCheck(e, ifDir) {
5380
5415
  if (ifDir && this.opts.nodir) return void 0;
@@ -5840,7 +5875,7 @@ const glob = Object.assign(glob_, {
5840
5875
  Glob,
5841
5876
  hasMagic,
5842
5877
  escape,
5843
- unescape: unescape$1
5878
+ unescape
5844
5879
  });
5845
5880
  glob.glob = glob;
5846
5881
 
@@ -5883,16 +5918,16 @@ var require_parser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/toml
5883
5918
  type: "literal",
5884
5919
  value: "]",
5885
5920
  description: "\"]\""
5886
- }, peg$c11 = function(name$1) {
5887
- addNode(node("ObjectPath", name$1, line, column));
5888
- }, peg$c12 = function(name$1) {
5889
- addNode(node("ArrayPath", name$1, line, column));
5890
- }, peg$c13 = function(parts, name$1) {
5891
- return parts.concat(name$1);
5892
- }, peg$c14 = function(name$1) {
5893
- return [name$1];
5894
- }, peg$c15 = function(name$1) {
5895
- return name$1;
5921
+ }, peg$c11 = function(name) {
5922
+ addNode(node("ObjectPath", name, line, column));
5923
+ }, peg$c12 = function(name) {
5924
+ addNode(node("ArrayPath", name, line, column));
5925
+ }, peg$c13 = function(parts, name) {
5926
+ return parts.concat(name);
5927
+ }, peg$c14 = function(name) {
5928
+ return [name];
5929
+ }, peg$c15 = function(name) {
5930
+ return name;
5896
5931
  }, peg$c16 = ".", peg$c17 = {
5897
5932
  type: "literal",
5898
5933
  value: ".",
@@ -5945,8 +5980,8 @@ var require_parser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/toml
5945
5980
  description: "\"E\""
5946
5981
  }, peg$c42 = function(left, right) {
5947
5982
  return node("Float", parseFloat(left + "e" + right), line, column);
5948
- }, peg$c43 = function(text$1) {
5949
- return node("Float", parseFloat(text$1), line, column);
5983
+ }, peg$c43 = function(text) {
5984
+ return node("Float", parseFloat(text), line, column);
5950
5985
  }, peg$c44 = "+", peg$c45 = {
5951
5986
  type: "literal",
5952
5987
  value: "+",
@@ -5959,8 +5994,8 @@ var require_parser = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/toml
5959
5994
  description: "\"-\""
5960
5995
  }, peg$c49 = function(digits) {
5961
5996
  return "-" + digits.join("");
5962
- }, peg$c50 = function(text$1) {
5963
- return node("Integer", parseInt(text$1, 10), line, column);
5997
+ }, peg$c50 = function(text) {
5998
+ return node("Integer", parseInt(text, 10), line, column);
5964
5999
  }, peg$c51 = "true", peg$c52 = {
5965
6000
  type: "literal",
5966
6001
  value: "true",
@@ -9627,9 +9662,10 @@ var require_toml = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/toml@3
9627
9662
  var import_toml = /* @__PURE__ */ __toESM(require_toml(), 1);
9628
9663
  /** Default configuration when no wesl.toml is found */
9629
9664
  const defaultWeslToml = {
9630
- weslFiles: ["shaders/**/*.w[eg]sl"],
9631
- weslRoot: "shaders",
9632
- dependencies: ["auto"]
9665
+ edition: "unstable_2025",
9666
+ include: ["shaders/**/*.w[eg]sl"],
9667
+ root: "shaders",
9668
+ dependencies: "auto"
9633
9669
  };
9634
9670
  /**
9635
9671
  * Load and parse a wesl.toml file from the fs.
@@ -9668,13 +9704,13 @@ async function findWeslToml(projectDir, specifiedToml) {
9668
9704
  parsedToml = defaultWeslToml;
9669
9705
  tomlDir = projectDir;
9670
9706
  }
9671
- const tomlToWeslRoot = path.resolve(tomlDir, parsedToml.weslRoot);
9707
+ const tomlToWeslRoot = path.resolve(tomlDir, parsedToml.root);
9672
9708
  const projectDirAbs = path.resolve(projectDir);
9673
- const resolvedWeslRoot = path.relative(projectDirAbs, tomlToWeslRoot);
9709
+ const resolvedRoot = path.relative(projectDirAbs, tomlToWeslRoot);
9674
9710
  return {
9675
9711
  tomlFile,
9676
9712
  tomlDir,
9677
- resolvedWeslRoot,
9713
+ resolvedRoot,
9678
9714
  toml: parsedToml
9679
9715
  };
9680
9716
  }
@@ -9697,8 +9733,8 @@ async function loadModules(projectDir, baseDir, srcGlob) {
9697
9733
  let resolvedSrcGlob;
9698
9734
  if (!baseDir || !srcGlob) {
9699
9735
  const tomlInfo = await findWeslToml(projectDir);
9700
- resolvedBaseDir = baseDir ?? tomlInfo.resolvedWeslRoot;
9701
- resolvedSrcGlob = srcGlob ?? tomlInfo.toml.weslFiles[0];
9736
+ resolvedBaseDir = baseDir ?? tomlInfo.resolvedRoot;
9737
+ resolvedSrcGlob = srcGlob ?? tomlInfo.toml.include[0];
9702
9738
  } else {
9703
9739
  resolvedBaseDir = baseDir;
9704
9740
  resolvedSrcGlob = srcGlob;
@@ -9721,48 +9757,48 @@ function zip(as, bs) {
9721
9757
  //#endregion
9722
9758
  //#region ../wesl-tooling/src/ParseDependencies.ts
9723
9759
  /**
9724
- * Find the wesl package dependencies in a set of WESL files
9725
- * (for packaging WESL files into a library)
9760
+ * Find package dependencies in WESL source files.
9761
+ *
9762
+ * Parses sources and partially binds identifiers to reveal unresolved package
9763
+ * references. Returns the longest resolvable npm subpath for each dependency.
9726
9764
  *
9727
- * Parse the WESL files and partially bind the identifiers,
9728
- * returning any identifiers that are not succesfully bound.
9729
- * Those identifiers are the package dependencies.
9765
+ * For example, 'foo::bar::baz' could resolve to:
9766
+ * - 'foo/bar' (package foo, export './bar' bundle)
9767
+ * - 'foo' (package foo, default export)
9730
9768
  *
9731
- * The dependency might be a default export bundle or
9732
- * a named export bundle. e.g. for 'foo::bar::baz', it could be
9733
- * . package foo, export '.' bundle, module bar
9734
- * . package foo, export './bar' bundle, element baz
9735
- * . package foo, export './bar/baz' bundle, module lib.wesl, element baz
9736
- * To distinguish these, we node resolve the longest path we can.
9769
+ * @param weslSrc - Record of WESL source files by path
9770
+ * @param projectDir - Project directory for resolving package imports
9771
+ * @returns Dependency paths in npm format (e.g., 'foo/bar', 'foo')
9737
9772
  */
9738
9773
  function parseDependencies(weslSrc, projectDir) {
9739
- const registry = parsedRegistry();
9774
+ let resolver;
9740
9775
  try {
9741
- parseIntoRegistry(weslSrc, registry);
9776
+ resolver = new RecordResolver(weslSrc);
9742
9777
  } catch (e) {
9743
- if (e.cause instanceof WeslParseError) console.error(e.message, "\n");
9744
- else throw e;
9778
+ if (e.cause instanceof WeslParseError) {
9779
+ console.error(e.message, "\n");
9780
+ return [];
9781
+ }
9782
+ throw e;
9745
9783
  }
9746
- const unbound = findUnboundIdents(registry);
9784
+ const unbound = findUnboundIdents(resolver);
9747
9785
  if (!unbound) return [];
9748
9786
  const pkgRefs = unbound.filter((modulePath) => modulePath.length > 1 && modulePath[0] !== "constants");
9749
9787
  if (pkgRefs.length === 0) return [];
9750
- const projectURL = pathToFileURL(path.resolve(path.join(projectDir, "foo"))).href;
9788
+ const projectURL = projectDirURL(projectDir);
9751
9789
  const deps = filterMap(pkgRefs, (mPath) => unboundToDependency(mPath, projectURL));
9752
9790
  return [...new Set(deps)];
9753
9791
  }
9754
- /**
9755
- * Find the longest resolvable npm subpath from a module path.
9792
+ /** Find longest resolvable npm subpath from module path segments.
9756
9793
  *
9757
- * @param mPath module path, e.g. ['foo', 'bar', 'baz', 'elem']
9758
- * @param importerURL URL of the importer, e.g. 'file:///path/to/project/foo/bar/baz.wesl' (doesn't need to be a real file)
9759
- * @returns longest resolvable subpath of mPath, e.g. 'foo/bar/baz' or 'foo/bar'
9794
+ * @param mPath - Module path segments (e.g., ['foo', 'bar', 'baz', 'elem'])
9795
+ * @param importerURL - Base URL for resolution (e.g., 'file:///path/to/project/')
9796
+ * @returns Longest resolvable subpath (e.g., 'foo/bar/baz' or 'foo')
9760
9797
  */
9761
9798
  function unboundToDependency(mPath, importerURL) {
9762
9799
  return [...exportSubpaths(mPath)].find((subPath) => tryResolve(subPath, importerURL));
9763
9800
  }
9764
- /** Try to resolve a path using node's resolve algorithm.
9765
- * @return the resolved path */
9801
+ /** Try Node.js module resolution; returns undefined if unresolvable. */
9766
9802
  function tryResolve(path$2, importerURL) {
9767
9803
  try {
9768
9804
  return resolve(path$2, importerURL);
@@ -9770,1435 +9806,60 @@ function tryResolve(path$2, importerURL) {
9770
9806
  return;
9771
9807
  }
9772
9808
  }
9773
- /**
9774
- * Yield possible export entry subpaths from module path
9775
- * longest subpath first.
9776
- */
9809
+ /** Yield possible export subpaths from module path, longest first.
9810
+ * Drops the last segment (element name) and iterates down. */
9777
9811
  function* exportSubpaths(mPath) {
9778
9812
  const longest = mPath.length - 1;
9779
9813
  for (let i = longest; i >= 0; i--) yield mPath.slice(0, i).join("/");
9780
9814
  }
9781
- /** @return WeslBundle instances referenced by wesl sources
9815
+ /**
9816
+ * Load WeslBundle instances referenced by WESL sources.
9782
9817
  *
9783
- * Parse the WESL files to find references to external WESL modules,
9784
- * and then load those modules (weslBundle.js files) using node dynamic imports.
9818
+ * Parses sources to find external module references, then dynamically imports
9819
+ * the corresponding weslBundle.js files.
9820
+ *
9821
+ * @param weslSrc - Record of WESL source files by path
9822
+ * @param projectDir - Project directory for resolving imports
9823
+ * @param packageName - Optional current package name
9824
+ * @param includeCurrentPackage - Include current package in results (default: false)
9825
+ * @returns Loaded WeslBundle instances
9785
9826
  */
9786
- async function dependencyBundles(weslSrc, projectDir) {
9827
+ async function dependencyBundles(weslSrc, projectDir, packageName, includeCurrentPackage = false) {
9787
9828
  const deps = parseDependencies(weslSrc, projectDir);
9788
- const projectURL = pathToFileURL(path.resolve(path.join(projectDir, "dummy.js"))).href;
9789
- const bundles = deps.map(async (dep) => {
9829
+ const filteredDeps = includeCurrentPackage ? deps : otherPackages(deps, packageName);
9830
+ const projectURL = projectDirURL(projectDir);
9831
+ const bundles = filteredDeps.map(async (dep) => {
9790
9832
  return (await import(resolve(dep, projectURL))).default;
9791
9833
  });
9792
9834
  return await Promise.all(bundles);
9793
9835
  }
9794
-
9795
- //#endregion
9796
- //#region ../wesl-tooling/src/Version.ts
9797
- /**
9798
- * @param projectDir - e.g., file:// URL of the directory containing package.json
9799
- * @returns the 'version' field from the package.json in the `projectDir`
9800
- */
9801
- async function versionFromPackageJson(projectDir) {
9802
- return (await import(new URL("./package.json", projectDir).href, { with: { type: "json" } })).default.version;
9803
- }
9804
-
9805
- //#endregion
9806
- //#region ../wesl/src/Util.ts
9807
- /**
9808
- * Maps an character position in a string to a 1-indexed line number, and 1-indexed column.
9809
- */
9810
- function offsetToLineNumber(offset, text$1) {
9811
- const safeOffset = Math.min(text$1.length, Math.max(0, offset));
9812
- let lineStartOffset = 0;
9813
- let lineNum = 1;
9814
- while (true) {
9815
- const lineEnd = text$1.indexOf("\n", lineStartOffset);
9816
- if (lineEnd === -1 || safeOffset <= lineEnd) {
9817
- const linePos = 1 + (safeOffset - lineStartOffset);
9818
- return [lineNum, linePos];
9819
- } else {
9820
- lineStartOffset = lineEnd + 1;
9821
- lineNum += 1;
9822
- }
9823
- }
9824
- }
9825
- /** Highlights an error.
9826
- *
9827
- * Returns a string with the line, and a string with the ^^^^ carets
9828
- */
9829
- function errorHighlight(source, span$1) {
9830
- let lineStartOffset = source.lastIndexOf("\n", span$1[0]);
9831
- if (lineStartOffset === -1) lineStartOffset = 0;
9832
- let lineEndOffset = source.indexOf("\n", span$1[0]);
9833
- if (lineEndOffset === -1) lineEndOffset = source.length;
9834
- const errorLength = span$1[1] - span$1[0];
9835
- const caretCount = Math.max(1, errorLength);
9836
- const linePos = span$1[0] - lineStartOffset;
9837
- return [source.slice(lineStartOffset, lineEndOffset), " ".repeat(linePos) + "^".repeat(caretCount)];
9838
- }
9839
-
9840
- //#endregion
9841
- //#region ../wesl/src/vlq/vlq.ts
9842
- /*!
9843
- Copyright (c) 2017-2021 [these people](https://github.com/Rich-Harris/vlq/graphs/contributors)
9844
-
9845
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9846
-
9847
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9848
-
9849
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9850
- */
9851
- const char_to_integer = {};
9852
- const integer_to_char = {};
9853
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split("").forEach((char, i) => {
9854
- char_to_integer[char] = i;
9855
- integer_to_char[i] = char;
9856
- });
9857
- function encodeVlq(value) {
9858
- if (typeof value === "number") return encode_integer(value);
9859
- let result = "";
9860
- for (let i = 0; i < value.length; i += 1) result += encode_integer(value[i]);
9861
- return result;
9862
- }
9863
- function encode_integer(num) {
9864
- let result = "";
9865
- let enc;
9866
- if (num < 0) enc = -num << 1 | 1;
9867
- else enc = num << 1;
9868
- do {
9869
- let clamped = enc & 31;
9870
- enc >>>= 5;
9871
- if (enc > 0) clamped |= 32;
9872
- result += integer_to_char[clamped];
9873
- } while (enc > 0);
9874
- return result;
9875
- }
9876
-
9877
- //#endregion
9878
- //#region ../wesl/src/ClickableError.ts
9879
- /** Throw an error with an embedded source map so that browser users can
9880
- * click on the error in the browser debug console and see the wesl source code. */
9881
- function throwClickableError(params) {
9882
- const { url, text: text$1, lineNumber, lineColumn, length, error } = params;
9883
- const mappings = encodeVlq([
9884
- 0,
9885
- 0,
9886
- Math.max(0, lineNumber - 1),
9887
- Math.max(0, lineColumn - 1)
9888
- ]) + "," + encodeVlq([
9889
- 18,
9890
- 0,
9891
- Math.max(0, lineNumber - 1),
9892
- Math.max(0, lineColumn - 1) + length
9893
- ]);
9894
- const sourceMap = {
9895
- version: 3,
9896
- file: null,
9897
- sources: [url],
9898
- sourcesContent: [text$1 ?? null],
9899
- names: [],
9900
- mappings
9901
- };
9902
- let generatedCode = `throw new Error(${JSON.stringify(error.message + "")})`;
9903
- generatedCode += "\n//# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
9904
- generatedCode += "\n//# sourceURL=" + sourceMap.sources[0];
9905
- let oldLimit = 0;
9906
- if ("stackTraceLimit" in Error) {
9907
- oldLimit = Error.stackTraceLimit;
9908
- Error.stackTraceLimit = 1;
9909
- }
9910
- try {
9911
- (0, eval)(generatedCode);
9912
- } catch (e) {
9913
- if ("stackTraceLimit" in Error) Error.stackTraceLimit = oldLimit;
9914
- error.message = "";
9915
- if (tracing) e.cause = error;
9916
- throw e;
9917
- }
9918
- }
9919
-
9920
- //#endregion
9921
- //#region ../wesl/src/Assertions.ts
9922
- /** checks whether a condition is true, otherwise throws */
9923
- function assertThat(condition, msg) {
9924
- if (!condition) throw new Error(msg);
9925
- }
9926
- /** when debug testing is enabled, checks whether a condition is true, otherwise throws */
9927
- function assertThatDebug(condition, msg) {
9928
- if (tracing) assertThat(condition, msg);
9929
- }
9930
- /**
9931
- * Useful to validate that all cases are handled,
9932
- * TypeScript should complain if this statement could possibly be executed.
9933
- *
9934
- * If this is somehow executed at runtime, throw an exception.
9935
- */
9936
- function assertUnreachable(value) {
9937
- throw new ErrorWithData("Unreachable value", { data: value });
9938
- }
9939
- var ErrorWithData = class extends Error {
9940
- data;
9941
- constructor(message, options) {
9942
- super(message, options);
9943
- this.data = options?.data;
9944
- }
9945
- };
9946
-
9947
- //#endregion
9948
- //#region ../wesl/src/Conditions.ts
9949
- /** Extract @if, @elif, or @else attribute from an array of attributes */
9950
- function findConditional(attributes) {
9951
- if (!attributes) return;
9952
- for (const attr of attributes) {
9953
- const kind$1 = attr.attribute.kind;
9954
- if (kind$1 === "@if" || kind$1 === "@elif" || kind$1 === "@else") return attr.attribute;
9955
- }
9956
- }
9957
-
9958
- //#endregion
9959
- //#region ../../node_modules/.pnpm/berry-pretty@0.0.5/node_modules/berry-pretty/dist/index.js
9960
- var spaces = memoize((nesting) => {
9961
- return " ".repeat(nesting);
9962
- });
9963
- var defaultCallerSize = 20;
9964
- var multiLinePad = "\n" + spaces(defaultCallerSize + 3);
9965
- function memoize(fn$1) {
9966
- const cache = /* @__PURE__ */ new Map();
9967
- return function(...args) {
9968
- const key = JSON.stringify(args);
9969
- if (cache.has(key)) return cache.get(key);
9970
- else {
9971
- const value = fn$1(...args);
9972
- cache.set(key, value);
9973
- return value;
9974
- }
9975
- };
9976
- }
9977
- if (typeof DOMRect === "undefined") globalThis.DOMRect = function() {};
9978
-
9979
- //#endregion
9980
- //#region ../wesl/src/Scope.ts
9981
- /** Combine two scope siblings.
9982
- * The first scope is mutated to append the contents of the second. */
9983
- function mergeScope(a, b) {
9984
- if (!b) return;
9985
- assertThatDebug(a.kind === b.kind);
9986
- assertThatDebug(a.parent === b.parent);
9987
- assertThatDebug(!b.condAttribute);
9988
- a.contents = a.contents.concat(b.contents);
9989
- }
9990
- /** reset scope and ident debugging ids */
9991
- function resetScopeIds() {
9992
- scopeId = 0;
9993
- identId = 0;
9836
+ /** Exclude current package from dependency list. */
9837
+ function otherPackages(deps, packageName) {
9838
+ if (!packageName) return deps;
9839
+ return deps.filter((dep) => dep !== packageName && !dep.startsWith(`${packageName}/`));
9994
9840
  }
9995
- let scopeId = 0;
9996
- let identId = 0;
9997
- function nextIdentId() {
9998
- return identId++;
9999
- }
10000
- /** make a new Scope object */
10001
- function emptyScope(parent, kind$1 = "scope") {
10002
- return {
10003
- id: scopeId++,
10004
- kind: kind$1,
10005
- parent,
10006
- contents: []
10007
- };
9841
+ /** Normalize project directory to file:// URL with trailing slash. */
9842
+ function projectDirURL(projectDir) {
9843
+ if (projectDir.startsWith("file://")) return projectDir.endsWith("/") ? projectDir : `${projectDir}/`;
9844
+ const fileUrl = pathToFileURL(projectDir).href;
9845
+ return fileUrl.endsWith("/") ? fileUrl : `${fileUrl}/`;
10008
9846
  }
10009
9847
 
10010
9848
  //#endregion
10011
- //#region ../wesl/src/WESLCollect.ts
10012
- function importElem(cc) {
10013
- const importElems = cc.tags.owo?.[0];
10014
- for (const importElem$1 of importElems) {
10015
- cc.app.stable.imports.push(importElem$1.imports);
10016
- addToOpenElem(cc, importElem$1);
10017
- }
10018
- }
10019
- /** add an elem to the .contents array of the currently containing element */
10020
- function addToOpenElem(cc, elem) {
10021
- const { openElems } = cc.app.context;
10022
- if (openElems?.length) openElems[openElems.length - 1].contents.push(elem);
10023
- }
10024
- /** create reference Ident and add to context */
10025
- function refIdent(cc) {
10026
- const { src, start, end } = cc;
10027
- const { srcModule } = cc.app.stable;
10028
- const originalName = src.slice(start, end);
10029
- const kind$1 = "ref";
10030
- const ident$1 = {
10031
- kind: kind$1,
10032
- originalName,
10033
- ast: cc.app.stable,
10034
- id: nextIdentId(),
10035
- refIdentElem: null
10036
- };
10037
- const identElem = {
10038
- kind: kind$1,
10039
- start,
10040
- end,
10041
- srcModule,
10042
- ident: ident$1
10043
- };
10044
- ident$1.refIdentElem = identElem;
10045
- saveIdent(cc, identElem);
10046
- addToOpenElem(cc, identElem);
10047
- return identElem;
10048
- }
10049
- /** create declaration Ident and add to context */
10050
- function declCollect(cc) {
10051
- return declCollectInternal(cc, false);
10052
- }
10053
- /** create global declaration Ident and add to context */
10054
- function globalDeclCollect(cc) {
10055
- return declCollectInternal(cc, true);
10056
- }
10057
- function declCollectInternal(cc, isGlobal) {
10058
- const { src, start, end } = cc;
10059
- const app = cc.app;
10060
- const { scope: containingScope } = app.context;
10061
- const { srcModule } = app.stable;
10062
- const originalName = src.slice(start, end);
10063
- const kind$1 = "decl";
10064
- const identElem = {
10065
- kind: kind$1,
10066
- start,
10067
- end,
10068
- srcModule,
10069
- ident: {
10070
- declElem: null,
10071
- kind: kind$1,
10072
- originalName,
10073
- containingScope,
10074
- isGlobal,
10075
- id: nextIdentId(),
10076
- srcModule
10077
- }
10078
- };
10079
- saveIdent(cc, identElem);
10080
- addToOpenElem(cc, identElem);
10081
- return identElem;
10082
- }
10083
- const typedDecl = collectElem("typeDecl", (cc, openElem) => {
10084
- const decl = cc.tags.decl_elem?.[0];
10085
- const typeRef = cc.tags.typeRefElem?.[0];
10086
- const typeScope = cc.tags.decl_type?.[0];
10087
- return withTextCover({
10088
- ...openElem,
10089
- decl,
10090
- typeScope,
10091
- typeRef
10092
- }, cc);
10093
- });
10094
- /** add Ident to current open scope, add IdentElem to current open element */
10095
- function saveIdent(cc, identElem) {
10096
- const { ident: ident$1 } = identElem;
10097
- ident$1.id = nextIdentId();
10098
- cc.app.context.scope.contents.push(ident$1);
10099
- }
10100
- /** start a new child lexical Scope */
10101
- function startScope(cc) {
10102
- startSomeScope("scope", cc);
10103
- }
10104
- /** start a new child partial Scope */
10105
- function startPartialScope(cc) {
10106
- startSomeScope("partial", cc);
10107
- }
10108
- /** start a new lexical or partial scope */
10109
- function startSomeScope(kind$1, cc) {
10110
- const { scope } = cc.app.context;
10111
- const newScope = emptyScope(scope, kind$1);
10112
- scope.contents.push(newScope);
10113
- cc.app.context.scope = newScope;
10114
- }
10115
- function completeScope(cc) {
10116
- return completeScopeInternal(cc, true);
10117
- }
10118
- function completeScopeNoIf(cc) {
10119
- return completeScopeInternal(cc, false);
10120
- }
10121
- function completeScopeInternal(cc, attachIfs) {
10122
- const weslContext = cc.app.context;
10123
- const completedScope = weslContext.scope;
10124
- const { parent } = completedScope;
10125
- if (parent) weslContext.scope = parent;
10126
- else if (tracing) console.log("ERR: completeScope, no parent scope", completedScope.contents);
10127
- if (attachIfs) completedScope.condAttribute = collectConditionalAttribute(cc, completedScope);
10128
- return completedScope;
10129
- }
10130
- /** return @if, @elif, or @else attribute from the 'attribute' or 'fn_attributes' tag */
10131
- function collectConditionalAttribute(cc, completedScope) {
10132
- if (completedScope.kind === "partial" && cc.tags.fn_name !== void 0) {
10133
- const flatAttrs = cc.tags.fn_attributes?.flat?.();
10134
- return findConditional(flatAttrs);
10135
- }
10136
- const attributes = cc.tags.attribute;
10137
- return findConditional(attributes);
10138
- }
10139
- function collectVarLike(kind$1) {
10140
- return collectElem(kind$1, (cc, openElem) => {
10141
- const name$1 = cc.tags.var_name?.[0];
10142
- const decl_scope = cc.tags.decl_scope?.[0];
10143
- const attributes = cc.tags.attribute;
10144
- const varElem = withTextCover({
10145
- ...openElem,
10146
- name: name$1,
10147
- attributes
10148
- }, cc);
10149
- const declIdent = name$1.decl.ident;
10150
- declIdent.declElem = varElem;
10151
- if (name$1.typeScope) {
10152
- mergeScope(name$1.typeScope, decl_scope);
10153
- declIdent.dependentScope = name$1.typeScope;
10154
- } else declIdent.dependentScope = decl_scope;
10155
- return varElem;
10156
- });
10157
- }
10158
- const aliasCollect = collectElem("alias", (cc, openElem) => {
10159
- const name$1 = cc.tags.alias_name?.[0];
10160
- const alias_scope = cc.tags.alias_scope?.[0];
10161
- const typeRef = cc.tags.typeRefElem?.[0];
10162
- const attributes = cc.tags.attributes?.flat() ?? [];
10163
- const aliasElem = withTextCover({
10164
- ...openElem,
10165
- name: name$1,
10166
- attributes,
10167
- typeRef
10168
- }, cc);
10169
- name$1.ident.dependentScope = alias_scope;
10170
- name$1.ident.declElem = aliasElem;
10171
- return aliasElem;
10172
- });
10173
- /**
10174
- * Collect a FnElem and associated scopes.
10175
- *
10176
- * Scope definition is a bit complicated in wgsl and wesl for fns.
10177
- * Here's what we collect for scopes for this example function:
10178
- * @if(true) fn foo(a: u32) -> @location(x) R { let y = a; }
10179
- *
10180
- * -{ // partial scope in case the whole shebang is prefixed by an `@if`
10181
- * %foo
10182
- *
10183
- * {<=%foo // foo decl references this header+returnType+body scope (for tracing dependencies from decls)
10184
- * x // for @location(x) (contains no decls, so ok to merge for tracing)
10185
- * %a u32 // merged from header scope
10186
- * R // merged from return type (contains no decls, so ok to merge for tracing)
10187
- * %y a // merged body scope
10188
- * }
10189
- * }
10190
- */
10191
- const fnCollect = collectElem("fn", (cc, openElem) => {
10192
- const ourTags = fnTags(cc);
10193
- const { name: name$1, headerScope, returnScope, bodyScope, body, params } = ourTags;
10194
- const { attributes, returnAttributes, returnType, fnScope } = ourTags;
10195
- const fnElem = {
10196
- ...openElem,
10197
- name: name$1,
10198
- attributes,
10199
- params,
10200
- returnAttributes,
10201
- body,
10202
- returnType
10203
- };
10204
- const mergedScope = headerScope;
10205
- if (returnScope) mergeScope(mergedScope, returnScope);
10206
- mergeScope(mergedScope, bodyScope);
10207
- const filtered = [];
10208
- for (const e of fnScope.contents) if (e === headerScope || e === returnScope) continue;
10209
- else if (e === bodyScope) filtered.push(mergedScope);
10210
- else filtered.push(e);
10211
- fnScope.contents = filtered;
10212
- name$1.ident.declElem = fnElem;
10213
- name$1.ident.dependentScope = mergedScope;
10214
- return fnElem;
10215
- });
10216
- /** Fetch and cast the collection tags for fnCollect
10217
- * LATER typechecking for collect! */
10218
- function fnTags(cc) {
10219
- const { fn_attributes, fn_name, fn_param, return_attributes } = cc.tags;
10220
- const { return_type } = cc.tags;
10221
- const { header_scope, return_scope, body_scope, body_statement } = cc.tags;
10222
- const { fn_partial_scope } = cc.tags;
10223
- return {
10224
- name: fn_name?.[0],
10225
- headerScope: header_scope?.[0],
10226
- returnScope: return_scope?.[0],
10227
- bodyScope: body_scope?.[0],
10228
- body: body_statement?.[0],
10229
- params: fn_param?.flat(3) ?? [],
10230
- attributes: fn_attributes?.flat(),
10231
- returnAttributes: return_attributes?.flat(),
10232
- returnType: return_type?.flat(3)[0],
10233
- fnScope: fn_partial_scope?.[0]
10234
- };
10235
- }
10236
- const collectFnParam = collectElem("param", (cc, openElem) => {
10237
- const name$1 = cc.tags.param_name?.[0];
10238
- const attributes = cc.tags.attributes?.flat() ?? [];
10239
- const paramElem = withTextCover({
10240
- ...openElem,
10241
- name: name$1,
10242
- attributes
10243
- }, cc);
10244
- name$1.decl.ident.declElem = paramElem;
10245
- return paramElem;
10246
- });
10247
- const collectStruct = collectElem("struct", (cc, openElem) => {
10248
- const name$1 = cc.tags.type_name?.[0];
10249
- const members = cc.tags.members;
10250
- const attributes = cc.tags.attributes?.flat() ?? [];
10251
- name$1.ident.dependentScope = cc.tags.struct_scope?.[0];
10252
- const elem = withTextCover({
10253
- ...openElem,
10254
- name: name$1,
10255
- attributes,
10256
- members
10257
- }, cc);
10258
- name$1.ident.declElem = elem;
10259
- return elem;
10260
- });
10261
- const collectStructMember = collectElem("member", (cc, openElem) => {
10262
- const name$1 = cc.tags.nameElem?.[0];
10263
- const typeRef = cc.tags.typeRefElem?.[0];
10264
- const attributes = cc.tags.attribute?.flat(3);
10265
- return withTextCover({
10266
- ...openElem,
10267
- name: name$1,
10268
- attributes,
10269
- typeRef
10270
- }, cc);
10271
- });
10272
- const specialAttribute = collectElem("attribute", (cc, openElem) => {
10273
- const attribute = cc.tags.attr_variant?.[0];
10274
- return {
10275
- ...openElem,
10276
- attribute
10277
- };
10278
- });
10279
- const assertCollect = attrElemCollect("assert");
10280
- const statementCollect = attrElemCollect("statement");
10281
- const switchClauseCollect = attrElemCollect("switch-clause");
10282
- /** @return a collector for container elem types that have only an attributes field */
10283
- function attrElemCollect(kind$1) {
10284
- return collectElem(kind$1, (cc, openElem) => {
10285
- const attributes = cc.tags.attribute?.flat(3);
10286
- return withTextCover({
10287
- ...openElem,
10288
- attributes
10289
- }, cc);
10290
- });
10291
- }
10292
- const collectAttribute = collectElem("attribute", (cc, openElem) => {
10293
- const params = cc.tags.attrParam;
10294
- const stdAttribute = {
10295
- kind: "@attribute",
10296
- name: cc.tags.name?.[0],
10297
- params
10298
- };
10299
- return {
10300
- ...openElem,
10301
- attribute: stdAttribute
10302
- };
10303
- });
10304
- const typeRefCollect = collectElem("type", (cc, openElem) => {
10305
- const templateParamsTemp = cc.tags.templateParam?.flat(3);
10306
- const typeRef = cc.tags.typeRefName?.[0];
10307
- const name$1 = typeof typeRef === "string" ? typeRef : typeRef.ident;
10308
- return withTextCover({
10309
- ...openElem,
10310
- name: name$1,
10311
- templateParams: templateParamsTemp
10312
- }, cc);
10313
- });
10314
- const expressionCollect = collectElem("expression", (cc, openElem) => {
10315
- return withTextCover({ ...openElem }, cc);
10316
- });
10317
- function globalAssertCollect(cc) {
10318
- const globalAssert = cc.tags.const_assert?.flat()[0];
10319
- const ast = cc.app.stable;
10320
- if (!ast.moduleAsserts) ast.moduleAsserts = [];
10321
- ast.moduleAsserts.push(globalAssert);
10322
- }
10323
- const stuffCollect = collectElem("stuff", (cc, openElem) => {
10324
- return withTextCover({ ...openElem }, cc);
10325
- });
10326
- const memberRefCollect = collectElem("memberRef", (cc, openElem) => {
10327
- const { component, structRef, extra_components } = cc.tags;
10328
- const member = component?.[0];
10329
- const name$1 = structRef?.flat()[0];
10330
- const extraComponents = extra_components?.flat()[0];
10331
- return withTextCover({
10332
- ...openElem,
10333
- name: name$1,
10334
- member,
10335
- extraComponents
10336
- }, cc);
10337
- });
10338
- function nameCollect(cc) {
10339
- const { start, end, src } = cc;
10340
- const elem = {
10341
- kind: "name",
10342
- start,
10343
- end,
10344
- name: src.slice(start, end)
10345
- };
10346
- addToOpenElem(cc, elem);
10347
- return elem;
10348
- }
10349
- const collectModule = collectElem("module", (cc, openElem) => {
10350
- const moduleElem = withTextCover(openElem, {
10351
- ...cc,
10352
- start: 0,
10353
- end: cc.src.length
10354
- });
10355
- const weslState = cc.app.stable;
10356
- weslState.moduleElem = moduleElem;
10357
- return moduleElem;
10358
- });
10359
- function directiveCollect(cc) {
10360
- const { start, end } = cc;
10361
- const directive = cc.tags.directive?.flat()[0];
10362
- const elem = {
10363
- kind: "directive",
10364
- attributes: cc.tags.attribute?.flat(),
10365
- start,
10366
- end,
10367
- directive
10368
- };
10369
- addToOpenElem(cc, elem);
10370
- return elem;
10371
- }
10372
- /**
10373
- * Collect a LexicalScope.
10374
- *
10375
- * The scope starts encloses all idents and subscopes inside the parser to which
10376
- * .collect is attached
10377
- */
10378
- const scopeCollect = {
10379
- before: startScope,
10380
- after: completeScope
10381
- };
10382
- /**
10383
- * Collect a LexicalScope.
10384
- *
10385
- * The scope starts encloses all idents and subscopes inside the parser to which
10386
- * .collect is attached
10387
- *
10388
- * '@if' attributes are not attached to the scope.
10389
- */
10390
- const scopeCollectNoIf = {
10391
- before: startScope,
10392
- after: completeScopeNoIf
10393
- };
10394
- /**
10395
- * Collect a PartialScope.
10396
- *
10397
- * The scope starts encloses all idents and subscopes inside the parser to which
10398
- * .collect is attached
10399
- */
10400
- const partialScopeCollect = {
10401
- before: startPartialScope,
10402
- after: completeScope
10403
- };
10404
- /** utility to collect an ElemWithContents
10405
- * starts the new element as the collection point corresponding
10406
- * to the start of the attached grammar and completes
10407
- * the element in the at the end of the grammar.
10408
- *
10409
- * In between the start and the end, the new element is available
10410
- * as an 'open' element in the collection context. While this element
10411
- * is 'open', other collected are added to the 'contents' field of this
10412
- * open element.
10413
- */
10414
- function collectElem(kind$1, fn$1) {
10415
- return {
10416
- before: (cc) => {
10417
- const partialElem = {
10418
- kind: kind$1,
10419
- contents: []
10420
- };
10421
- cc.app.context.openElems.push(partialElem);
10422
- },
10423
- after: (cc) => {
10424
- const partialElem = cc.app.context.openElems.pop();
10425
- console.assert(partialElem && partialElem.kind === kind$1);
10426
- const elem = fn$1(cc, {
10427
- ...partialElem,
10428
- start: cc.start,
10429
- end: cc.end
10430
- });
10431
- if (elem) addToOpenElem(cc, elem);
10432
- return elem;
10433
- }
10434
- };
10435
- }
10436
- /**
10437
- * @return a copy of the element with contents extended
10438
- * to include TextElems to cover the entire range.
10439
- */
10440
- function withTextCover(elem, cc) {
10441
- const contents = coverWithText(cc, elem);
10442
- return {
10443
- ...elem,
10444
- contents
10445
- };
10446
- }
10447
- /** cover the entire source range with Elems by creating TextElems to
10448
- * cover any parts of the source that are not covered by other elems
10449
- * @returns the existing elems combined with any new TextElems, in src order */
10450
- function coverWithText(cc, elem) {
10451
- let { start: pos } = cc;
10452
- const ast = cc.app.stable;
10453
- const { contents, end } = elem;
10454
- const sorted = contents.sort((a, b) => a.start - b.start);
10455
- const elems = [];
10456
- for (const elem$1 of sorted) {
10457
- if (pos < elem$1.start) elems.push(makeTextElem(elem$1.start));
10458
- elems.push(elem$1);
10459
- pos = elem$1.end;
10460
- }
10461
- if (pos < end) elems.push(makeTextElem(end));
10462
- return elems;
10463
- function makeTextElem(end$1) {
10464
- return {
10465
- kind: "text",
10466
- start: pos,
10467
- end: end$1,
10468
- srcModule: ast.srcModule
10469
- };
10470
- }
10471
- }
10472
-
10473
- //#endregion
10474
- //#region ../wesl/src/parse/Keywords.ts
10475
- /** https://www.w3.org/TR/WGSL/#keyword-summary */
10476
- const keywords = `alias break case const const_assert continue continuing
10477
- default diagnostic discard else enable false fn for if
10478
- let loop override requires return struct switch true var while`.split(/\s+/);
10479
- /** https://www.w3.org/TR/WGSL/#reserved-words */
10480
- const reservedWords = `NULL Self abstract active alignas alignof as asm asm_fragment async attribute auto await
10481
- become binding_array cast catch class co_await co_return co_yield coherent column_major
10482
- common compile compile_fragment concept const_cast consteval constexpr constinit crate
10483
- debugger decltype delete demote demote_to_helper do dynamic_cast
10484
- enum explicit export extends extern external fallthrough filter final finally friend from fxgroup
10485
- get goto groupshared highp impl implements import inline instanceof interface layout lowp
10486
- macro macro_rules match mediump meta mod module move mut mutable
10487
- namespace new nil noexcept noinline nointerpolation non_coherent noncoherent noperspective null nullptr
10488
- of operator package packoffset partition pass patch pixelfragment precise precision premerge
10489
- priv protected pub public readonly ref regardless register reinterpret_cast require resource restrict
10490
- self set shared sizeof smooth snorm static static_assert static_cast std subroutine super
10491
- target template this thread_local throw trait try type typedef typeid typename typeof
10492
- union unless unorm unsafe unsized use using varying virtual volatile wgsl where with writeonly yield`.split(/\s+/);
10493
-
10494
- //#endregion
10495
- //#region ../wesl/src/parse/WeslStream.ts
10496
- /** Whitespaces including new lines */
10497
- const blankspaces = /[ \t\n\v\f\r\u{0085}\u{200E}\u{200F}\u{2028}\u{2029}]+/u;
10498
- const symbolSet = "& && -> @ / ! [ ] { } :: : , == = != >>= >> >= > <<= << <= < % - -- . + ++ | || ( ) ; * ~ ^ // /* */ += -= *= /= %= &= |= ^= _";
10499
- const ident = /(?:(?:[_\p{XID_Start}][\p{XID_Continue}]+)|(?:[\p{XID_Start}]))/u;
10500
- const keywordOrReserved = new Set(keywords.concat(reservedWords));
10501
- const weslMatcher = new RegexMatchers({
10502
- word: ident,
10503
- number: new RegExp(/(?:0[fh])|(?:[1-9][0-9]*[fh])/.source + /|(?:[0-9]*\.[0-9]+(?:[eE][+-]?[0-9]+)?[fh]?)/.source + /|(?:[0-9]+\.[0-9]*(?:[eE][+-]?[0-9]+)?[fh]?)/.source + /|(?:[0-9]+[eE][+-]?[0-9]+[fh]?)/.source + /|(?:0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+(?:[pP][+-]?[0-9]+[fh]?)?)/.source + /|(?:0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*(?:[pP][+-]?[0-9]+[fh]?)?)/.source + /|(?:0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fh]?)/.source + /|(?:0[xX][0-9a-fA-F]+[iu]?)/.source + /|(?:0[iu]?)|(?:[1-9][0-9]*[iu]?)/.source),
10504
- blankspaces,
10505
- commentStart: /\/\/|\/\*/,
10506
- symbol: matchOneOf(symbolSet),
10507
- invalid: /[^]/
10508
- });
10509
- /** To mark parts of the grammar implementation that are WESL specific extensions */
10510
- function weslExtension(combinator) {
10511
- return combinator;
10512
- }
10513
- /** A stream that produces WESL tokens, skipping over comments and white space */
10514
- var WeslStream = class {
10515
- stream;
10516
- /** New line */
10517
- eolPattern = /[\n\v\f\u{0085}\u{2028}\u{2029}]|\r\n?/gu;
10518
- /** Block comments */
10519
- blockCommentPattern = /\/\*|\*\//g;
10520
- src;
10521
- constructor(src) {
10522
- this.src = src;
10523
- this.stream = new CachingStream(new MatchersStream(src, weslMatcher));
10524
- }
10525
- checkpoint() {
10526
- return this.stream.checkpoint();
10527
- }
10528
- reset(position) {
10529
- this.stream.reset(position);
10530
- }
10531
- nextToken() {
10532
- while (true) {
10533
- const token$1 = this.stream.nextToken();
10534
- if (token$1 === null) return null;
10535
- const kind$1 = token$1.kind;
10536
- if (kind$1 === "blankspaces") continue;
10537
- else if (kind$1 === "commentStart") if (token$1.text === "//") this.stream.reset(this.skipToEol(token$1.span[1]));
10538
- else this.stream.reset(this.skipBlockComment(token$1.span[1]));
10539
- else if (kind$1 === "word") {
10540
- const returnToken = token$1;
10541
- if (keywordOrReserved.has(token$1.text)) returnToken.kind = "keyword";
10542
- return returnToken;
10543
- } else if (kind$1 === "invalid") throw new ParseError("Invalid token " + token$1.text, token$1.span);
10544
- else return token$1;
10545
- }
10546
- }
10547
- skipToEol(position) {
10548
- this.eolPattern.lastIndex = position;
10549
- if (this.eolPattern.exec(this.src) === null) return this.src.length;
10550
- else return this.eolPattern.lastIndex;
10551
- }
10552
- skipBlockComment(start) {
10553
- let position = start;
10554
- while (true) {
10555
- this.blockCommentPattern.lastIndex = position;
10556
- const result = this.blockCommentPattern.exec(this.src);
10557
- if (result === null) throw new ParseError("Unclosed block comment!", [position, position]);
10558
- else if (result[0] === "*/") return this.blockCommentPattern.lastIndex;
10559
- else if (result[0] === "/*") position = this.skipBlockComment(this.blockCommentPattern.lastIndex);
10560
- else throw new Error("Unreachable, invalid block comment pattern");
10561
- }
10562
- }
10563
- /**
10564
- * Only matches the `<` token if it is a template
10565
- * Precondition: An ident was parsed right before this.
10566
- * Runs the [template list discovery algorithm](https://www.w3.org/TR/WGSL/#template-list-discovery).
10567
- */
10568
- nextTemplateStartToken() {
10569
- const startPosition = this.stream.checkpoint();
10570
- const token$1 = this.nextToken();
10571
- this.stream.reset(startPosition);
10572
- if (token$1 === null) return null;
10573
- if (token$1.kind !== "symbol") return null;
10574
- if (token$1.text === "<") if (this.isTemplateStart(token$1.span[1])) {
10575
- this.stream.reset(token$1.span[1]);
10576
- return token$1;
10577
- } else {
10578
- this.stream.reset(startPosition);
10579
- return null;
10580
- }
10581
- else return null;
10582
- }
10583
- nextTemplateEndToken() {
10584
- const startPosition = this.stream.checkpoint();
10585
- const token$1 = this.nextToken();
10586
- this.stream.reset(startPosition);
10587
- if (token$1 === null) return null;
10588
- if (token$1.kind === "symbol" && token$1.text[0] === ">") {
10589
- const tokenPosition = token$1.span[0];
10590
- this.stream.reset(tokenPosition + 1);
10591
- return {
10592
- kind: "symbol",
10593
- span: [tokenPosition, tokenPosition + 1],
10594
- text: ">"
10595
- };
10596
- } else return null;
10597
- }
10598
- isTemplateStart(afterToken) {
10599
- this.stream.reset(afterToken);
10600
- let pendingCounter = 1;
10601
- while (true) {
10602
- const nextToken = this.stream.nextToken();
10603
- if (nextToken === null) return false;
10604
- if (nextToken.kind !== "symbol") continue;
10605
- if (nextToken.text === "<") pendingCounter += 1;
10606
- else if (nextToken.text[0] === ">") {
10607
- if (nextToken.text === ">" || nextToken.text === ">=") pendingCounter -= 1;
10608
- else if (nextToken.text === ">>=" || nextToken.text === ">>") pendingCounter -= 2;
10609
- else throw new Error("This case should never be reached, looks like we forgot one of the tokens that start with >");
10610
- if (pendingCounter <= 0) return true;
10611
- } else if (nextToken.text === "(") this.skipBracketsTo(")");
10612
- else if (nextToken.text === "[") this.skipBracketsTo("]");
10613
- else if (nextToken.text === "==" || nextToken.text === "!=" || nextToken.text === ";" || nextToken.text === "{" || nextToken.text === ":" || nextToken.text === "&&" || nextToken.text === "||") return false;
10614
- }
10615
- }
10616
- /**
10617
- * Call this after consuming an opening bracket.
10618
- * Skips until a closing bracket. This also consumes the closing bracket.
10619
- */
10620
- skipBracketsTo(closingBracket) {
10621
- while (true) {
10622
- const nextToken = this.stream.nextToken();
10623
- if (nextToken === null) {
10624
- const after = this.stream.checkpoint();
10625
- throw new ParseError("Unclosed bracket!", [after, after]);
10626
- }
10627
- if (nextToken.kind !== "symbol") continue;
10628
- if (nextToken.text === "(") this.skipBracketsTo(")");
10629
- else if (nextToken.text === "[") this.skipBracketsTo("]");
10630
- else if (nextToken.text === closingBracket) return;
10631
- }
10632
- }
10633
- };
10634
- const templateOpen = withStreamAction((stream$1) => {
10635
- return stream$1.nextTemplateStartToken();
10636
- });
10637
- const templateClose = withStreamAction((stream$1) => {
10638
- return stream$1.nextTemplateEndToken();
10639
- });
10640
-
10641
- //#endregion
10642
- //#region ../wesl/src/parse/AttributeGrammar.ts
10643
- const attribute_if_primary_expression = or(tokenOf("keyword", ["true", "false"]).map(makeLiteral), delimited(token("symbol", "("), fn(() => attribute_if_expression), token("symbol", ")")).map(makeParenthesizedExpression), tokenKind("word").map(makeTranslateTimeFeature));
10644
- const attribute_if_unary_expression = or(seq(token("symbol", "!").map(makeUnaryOperator), fn(() => attribute_if_unary_expression)).map(makeUnaryExpression), attribute_if_primary_expression);
10645
- const attribute_if_expression = weslExtension(seq(attribute_if_unary_expression, or(repeatPlus(seq(token("symbol", "||").map(makeBinaryOperator), req(attribute_if_unary_expression, "invalid expression, expected expression"))), repeatPlus(seq(token("symbol", "&&").map(makeBinaryOperator), req(attribute_if_unary_expression, "invalid expression, expected expression"))), yes().map(() => []))).map(makeRepeatingBinaryExpression));
10646
- /** Base parser for @if attributes without collection - use in seq() compositions */
10647
- const if_attribute_base = preceded(seq("@", weslExtension("if")), span(delimited("(", fn(() => attribute_if_expression), seq(opt(","), ")"))).map(makeTranslateTimeExpressionElem)).map(makeIfAttribute).ptag("attr_variant");
10648
- /** Base parser for @elif attributes without collection - use in seq() compositions */
10649
- const elif_attribute_base = preceded(seq("@", weslExtension("elif")), span(delimited("(", fn(() => attribute_if_expression), seq(opt(","), ")"))).map(makeTranslateTimeExpressionElem)).map(makeElifAttribute).ptag("attr_variant");
10650
- /** Base parser for @else attributes without collection - use in seq() compositions */
10651
- const else_attribute_base = preceded(seq("@", weslExtension("else")), yes).map(makeElseAttribute).ptag("attr_variant");
10652
- /** Collected parser for @if attributes - use standalone, not in seq() */
10653
- const if_attribute = tagScope(if_attribute_base.collect(specialAttribute));
10654
- /** Collected parser for @elif attributes - use standalone, not in seq() */
10655
- const elif_attribute = tagScope(elif_attribute_base.collect(specialAttribute));
10656
- /** Collected parser for @else attributes - use standalone, not in seq() */
10657
- const else_attribute = tagScope(else_attribute_base.collect(specialAttribute));
10658
- function makeIfAttribute(param) {
10659
- return {
10660
- kind: "@if",
10661
- param
10662
- };
10663
- }
10664
- function makeElifAttribute(param) {
10665
- return {
10666
- kind: "@elif",
10667
- param
10668
- };
10669
- }
10670
- function makeElseAttribute() {
10671
- return { kind: "@else" };
10672
- }
10673
- function makeTranslateTimeExpressionElem(args) {
10674
- return {
10675
- kind: "translate-time-expression",
10676
- expression: args.value,
10677
- span: args.span
10678
- };
10679
- }
10680
- function makeLiteral(token$1) {
10681
- return {
10682
- kind: "literal",
10683
- value: token$1.text,
10684
- span: token$1.span
10685
- };
10686
- }
10687
- function makeTranslateTimeFeature(token$1) {
10688
- return {
10689
- kind: "translate-time-feature",
10690
- name: token$1.text,
10691
- span: token$1.span
10692
- };
10693
- }
10694
- function makeParenthesizedExpression(expression$1) {
10695
- return {
10696
- kind: "parenthesized-expression",
10697
- expression: expression$1
10698
- };
10699
- }
10700
- function makeUnaryOperator(token$1) {
10701
- return {
10702
- value: token$1.text,
10703
- span: token$1.span
10704
- };
10705
- }
10706
- function makeBinaryOperator(token$1) {
10707
- return {
10708
- value: token$1.text,
10709
- span: token$1.span
10710
- };
10711
- }
10712
- function makeUnaryExpression([operator, expression$1]) {
10713
- return {
10714
- kind: "unary-expression",
10715
- operator,
10716
- expression: expression$1
10717
- };
10718
- }
10719
- function makeRepeatingBinaryExpression([start, repeating]) {
10720
- let result = start;
10721
- for (const [op, left] of repeating) result = {
10722
- kind: "binary-expression",
10723
- operator: op,
10724
- left: result,
10725
- right: left
10726
- };
10727
- return result;
10728
- }
10729
-
10730
- //#endregion
10731
- //#region ../wesl/src/parse/WeslBaseGrammar.ts
10732
- const word = kind("word");
10733
- const keyword = kind("keyword");
10734
- const qualified_ident = withSepPlus("::", or(word, keyword, "package", "super"));
10735
- const number = kind("number");
10736
-
10737
- //#endregion
10738
- //#region ../wesl/src/parse/ImportGrammar.ts
10739
- function makeStatement(segments, finalSegment) {
10740
- return {
10741
- kind: "import-statement",
10742
- segments,
10743
- finalSegment
10744
- };
10745
- }
10746
- function makeSegment(name$1) {
10747
- return {
10748
- kind: "import-segment",
10749
- name: name$1
10750
- };
10751
- }
10752
- function makeCollection(subtrees) {
10753
- return {
10754
- kind: "import-collection",
10755
- subtrees
10756
- };
10757
- }
10758
- function makeItem(name$1, as) {
10759
- return {
10760
- kind: "import-item",
10761
- name: name$1,
10762
- as
10763
- };
10764
- }
10765
- function prependSegments(segments, statement$1) {
10766
- statement$1.segments = segments.concat(statement$1.segments);
10767
- return statement$1;
10768
- }
10769
- let import_collection = null;
10770
- const import_path_or_item = seq(preceded(not(or("super", "package", "import", "as")), or(word, keyword)), or(preceded("::", req(or(fn(() => import_collection), fn(() => import_path_or_item)), "invalid import, expected '{' or name")), preceded("as", req(word, "invalid alias, expected name")).map((v) => makeItem("", v)), yes().map(() => makeItem("")))).map(([name$1, next]) => {
10771
- if (next.kind === "import-collection") return makeStatement([makeSegment(name$1)], next);
10772
- else if (next.kind === "import-statement") return prependSegments([makeSegment(name$1)], next);
10773
- else if (next.kind === "import-item") {
10774
- next.name = name$1;
10775
- return makeStatement([], next);
10776
- } else assertUnreachable(next);
10777
- });
10778
- import_collection = delimited("{", withSepPlus(",", () => import_path_or_item).map(makeCollection), req("}", "invalid import collection, expected }"));
10779
- const import_relative = or(terminated("package", req("::", "invalid import, expected '::'")).map((v) => [makeSegment(v)]), repeatPlus(terminated("super", req("::", "invalid import, expected '::'")).map(makeSegment)));
10780
- const import_statement_base = delimited("import", seqObj({
10781
- relative: opt(import_relative),
10782
- collection_or_statement: req(or(import_collection, import_path_or_item), "invalid import, expected { or name")
10783
- }).map(({ relative, collection_or_statement }) => {
10784
- if (collection_or_statement.kind === "import-statement") return prependSegments(relative ?? [], collection_or_statement);
10785
- else return makeStatement(relative ?? [], collection_or_statement);
10786
- }), req(";", "invalid import, expected ';'"));
10787
- function wrapAttributes(rawAttributes) {
10788
- return rawAttributes.map((attribute) => ({
10789
- kind: "attribute",
10790
- attribute,
10791
- contents: [],
10792
- start: 0,
10793
- end: 0
10794
- }));
10795
- }
10796
- const import_statement = span(seq(repeat(or(if_attribute_base, elif_attribute_base, else_attribute_base)), import_statement_base)).map(({ value: [rawAttributes, imports], span: span$1 }) => {
10797
- const importElem$1 = {
10798
- kind: "import",
10799
- imports,
10800
- start: span$1[0],
10801
- end: span$1[1]
10802
- };
10803
- if (rawAttributes.length > 0) return {
10804
- ...importElem$1,
10805
- attributes: wrapAttributes(rawAttributes)
10806
- };
10807
- return importElem$1;
10808
- });
10809
- /** parse a WESL style wgsl import statement. */
10810
- const weslImports = tagScope(repeat(import_statement).ptag("owo").collect(importElem));
10811
- if (tracing) {
10812
- const names = {
10813
- import_collection,
10814
- import_path_or_item,
10815
- import_relative,
10816
- import_statement,
10817
- weslImports
10818
- };
10819
- Object.entries(names).forEach(([name$1, parser$1]) => {
10820
- parser$1.setTraceName(name$1);
10821
- });
10822
- }
10823
-
10824
- //#endregion
10825
- //#region ../wesl/src/parse/WeslExpression.ts
10826
- const opt_template_list = opt(seq(templateOpen, withSepPlus(",", () => template_parameter), req(templateClose, "invalid template, expected '>'")));
10827
- const other_address_space = or("private", "workgroup", "uniform", "function");
10828
- const storage_address_space = seq("storage", opt(seq(",", or("read", "read_write"))));
10829
- const var_template_list = opt(seq(templateOpen, or(storage_address_space, other_address_space), req(templateClose, "invalid template, expected '>'")));
10830
- const template_elaborated_ident = seq(qualified_ident.collect(refIdent), opt_template_list);
10831
- const literal = or("true", "false", number);
10832
- const paren_expression = seq("(", () => expression, req(")", "invalid expression, expected ')'"));
10833
- const primary_expression = or(literal, paren_expression, seq(template_elaborated_ident, opt(fn(() => argument_expression_list))));
10834
- const component_or_swizzle = repeatPlus(or(preceded(".", word), collectArray(delimited("[", () => expression, req("]", "invalid expression, expected ']'")))));
10835
- /** parse simple struct.member style references specially, for binding struct lowering */
10836
- const simple_component_reference = tagScope(seq(qualified_ident.collect(refIdent, "structRef"), seq(".", word.collect(nameCollect, "component")), opt(component_or_swizzle.collect(stuffCollect, "extra_components"))).collect(memberRefCollect));
10837
- const unary_expression = or(seq(tokenOf("symbol", [
10838
- "!",
10839
- "&",
10840
- "*",
10841
- "-",
10842
- "~"
10843
- ]), () => unary_expression), or(simple_component_reference, seq(primary_expression, opt(component_or_swizzle))));
10844
- const bitwise_post_unary = or(repeatPlus(seq("&", unary_expression)), repeatPlus(seq("^", unary_expression)), repeatPlus(seq("|", unary_expression)));
10845
- const multiplicative_operator = or("%", "*", "/");
10846
- const additive_operator = or("+", "-");
10847
- const shift_post_unary = (inTemplate) => {
10848
- const shift_left = seq("<<", unary_expression);
10849
- const shift_right = seq(">>", unary_expression);
10850
- const mul_add = seq(repeat(seq(multiplicative_operator, unary_expression)), repeat(seq(additive_operator, unary_expression, repeat(seq(multiplicative_operator, unary_expression)))));
10851
- return inTemplate ? or(shift_left, mul_add) : or(shift_left, shift_right, mul_add);
10852
- };
10853
- const relational_post_unary = (inTemplate) => {
10854
- return seq(shift_post_unary(inTemplate), opt(seq(inTemplate ? tokenOf("symbol", [
10855
- "<",
10856
- "<=",
10857
- "!=",
10858
- "=="
10859
- ]) : tokenOf("symbol", [
10860
- ">",
10861
- ">=",
10862
- "<",
10863
- "<=",
10864
- "!=",
10865
- "=="
10866
- ]), unary_expression, shift_post_unary(inTemplate))));
10867
- };
10868
- /** The expression parser exists in two variants
10869
- * `true` is template-expression: Refuses to parse parse symbols like `&&` and `||`.
10870
- * `false` is maybe-template-expression: Does the template disambiguation.
10871
- */
10872
- const expressionParser = (inTemplate) => {
10873
- return seq(unary_expression, or(bitwise_post_unary, seq(relational_post_unary(inTemplate), inTemplate ? yes() : or(repeatPlus(seq("||", seq(unary_expression, relational_post_unary(false)))), repeatPlus(seq("&&", seq(unary_expression, relational_post_unary(false)))), yes().map(() => [])))));
10874
- };
10875
- const maybe_template = false;
10876
- const expression = expressionParser(maybe_template);
10877
- const template_arg_expression = expressionParser(true);
10878
- const std_type_specifier = seq(qualified_ident.collect(refIdent, "typeRefName"), () => opt_template_list).collect(typeRefCollect);
10879
- const type_specifier = tagScope(std_type_specifier).ctag("typeRefElem");
10880
- /** a template_arg_expression with additional collection for parameters
10881
- * that are types like array<f32> vs. expressions like 1+2 */
10882
- const template_parameter = or(type_specifier.ctag("templateParam"), template_arg_expression.collect(expressionCollect, "templateParam"));
10883
- const argument_expression_list = seq("(", withSep(",", expression), req(")", "invalid fn arguments, expected ')'"));
10884
- if (tracing) {
10885
- const names = {
10886
- opt_template_list,
10887
- other_address_space,
10888
- storage_address_space,
10889
- var_template_list,
10890
- template_elaborated_ident,
10891
- primary_expression,
10892
- literal,
10893
- paren_expression,
10894
- component_or_swizzle,
10895
- simple_component_reference,
10896
- unary_expression,
10897
- bitwise_post_unary,
10898
- multiplicative_operator,
10899
- additive_operator,
10900
- expression,
10901
- template_arg_expression,
10902
- std_type_specifier,
10903
- type_specifier,
10904
- template_parameter,
10905
- argument_expression_list
10906
- };
10907
- Object.entries(names).forEach(([name$1, parser$1]) => {
10908
- parser$1.setTraceName(name$1);
10909
- });
10910
- }
10911
-
10912
- //#endregion
10913
- //#region ../wesl/src/parse/WeslGrammar.ts
10914
- const name = tokenKind("word").map(makeName);
10915
- const diagnostic_rule_name = seq(name, opt(preceded(".", req(name, "invalid diagnostic rule name, expected name"))));
10916
- const diagnostic_control = delimited("(", req(separated_pair(name, ",", diagnostic_rule_name), "invalid diagnostic control, expected rule name"), seq(opt(","), req(")", "invalid diagnostic control, expected ')'")));
10917
- /** list of words that aren't identifiers (e.g. for @interpolate) */
10918
- const name_list = withSep(",", name, { requireOne: true });
10919
- const special_attribute = tagScope(preceded("@", or(or("compute", "const", "fragment", "invariant", "must_use", "vertex").map((name$1) => makeStandardAttribute([name$1, []])), preceded("interpolate", req(delimited("(", name_list, ")"), "invalid @interpolate, expected '('")).map(makeInterpolateAttribute), preceded("builtin", req(delimited("(", name, ")"), "invalid @builtin, expected '('")).map(makeBuiltinAttribute), preceded("diagnostic", req(diagnostic_control, "invalid @diagnostic, expected '('")).map(makeDiagnosticAttribute)).ptag("attr_variant")).collect(specialAttribute));
10920
- const normal_attribute = tagScope(preceded("@", or(seq(or("workgroup_size", "align", "binding", "blend_src", "group", "id", "location", "size").ptag("name"), req(() => attribute_argument_list, "invalid attribute, expected '('")), seq(word.ptag("name"), opt(() => attribute_argument_list)))).collect(collectAttribute));
10921
- const attribute_argument_list = delimited("(", withSep(",", span(fn(() => expression)).collect(expressionCollect, "attrParam")), req(")", "invalid attribute arguments, expected ')'"));
10922
- const attribute_no_if = or(special_attribute, normal_attribute).ctag("attribute");
10923
- const attribute_incl_if = or(if_attribute, elif_attribute, else_attribute, special_attribute, normal_attribute).ctag("attribute");
10924
- const opt_attributes = repeat(attribute_incl_if);
10925
- const opt_attributes_no_if = repeat(attribute_no_if);
10926
- const globalTypeNameDecl = req(word.collect(globalDeclCollect, "type_name"), "invalid type name, expected a name");
10927
- const fnNameDecl = req(word.collect(globalDeclCollect, "fn_name"), "missing fn name");
10928
- const optionally_typed_ident = tagScope(seq(word.collect(declCollect, "decl_elem"), opt(seq(":", type_specifier))).collect(typedDecl)).ctag("var_name");
10929
- const req_optionally_typed_ident = req(optionally_typed_ident, "invalid ident");
10930
- const global_ident = tagScope(req(seq(word.collect(globalDeclCollect, "decl_elem"), opt(seq(":", type_specifier.collect(scopeCollectNoIf, "decl_type")))).collect(typedDecl), "expected identifier")).ctag("var_name");
10931
- const struct_member = tagScope(seq(opt_attributes, word.collect(nameCollect, "nameElem"), req(":", "invalid struct member, expected ':'"), req(type_specifier, "invalid struct member, expected type specifier")).collect(collectStructMember)).ctag("members");
10932
- const struct_decl = seq(weslExtension(opt_attributes).collect((cc) => cc.tags.attribute, "attributes"), "struct", req(globalTypeNameDecl, "invalid struct, expected name"), seq(req("{", "invalid struct, expected '{'"), withSepPlus(",", struct_member), req("}", "invalid struct, expected '}'")).collect(scopeCollect, "struct_scope")).collect(collectStruct);
10933
- /** Also covers func_call_statement.post.ident */
10934
- const fn_call = seq(qualified_ident.collect(refIdent), () => opt_template_list, argument_expression_list);
10935
- const fnParam = tagScope(seq(opt_attributes.collect((cc) => cc.tags.attribute, "attributes"), word.collect(declCollect, "decl_elem"), opt(seq(":", req(type_specifier, "invalid fn parameter, expected type specifier"))).collect(typedDecl, "param_name")).collect(collectFnParam)).ctag("fn_param");
10936
- const fnParamList = seq("(", withSep(",", fnParam), ")");
10937
- const local_variable_decl = seq("var", () => var_template_list, req_optionally_typed_ident, opt(seq("=", () => expression))).collect(collectVarLike("var"));
10938
- const global_variable_decl = seq(opt_attributes, "var", () => var_template_list, global_ident, opt(seq("=", () => expression.collect(scopeCollectNoIf, "decl_scope"))), ";").collect(collectVarLike("gvar")).collect(partialScopeCollect);
10939
- const unscoped_compound_statement = seq(opt_attributes, text("{"), repeat(() => statement), req("}", "invalid block, expected }")).collect(statementCollect);
10940
- const compound_statement = tagScope(seq(opt_attributes, seq(text("{"), repeat(() => statement), req("}", "invalid block, expected '}'")).collect(scopeCollect)).collect(statementCollect));
10941
- const for_init = seq(opt_attributes, or(fn_call, () => variable_or_value_statement, () => variable_updating_statement));
10942
- const for_update = seq(opt_attributes, or(fn_call, () => variable_updating_statement));
10943
- const for_statement = seq("for", seq(req("(", "invalid for loop, expected '('"), opt(for_init), req(";", "invalid for loop, expected ';'"), opt(expression), req(";", "invalid for loop, expected ';'"), opt(for_update), req(")", "invalid for loop, expected ')'"), unscoped_compound_statement).collect(scopeCollect));
10944
- const if_statement = seq("if", req(seq(expression, compound_statement), "invalid if statement"), repeat(seq("else", "if", req(seq(expression, compound_statement), "invalid else if branch"))), opt(seq("else", req(compound_statement, "invalid else branch, expected '{'"))));
10945
- const loop_statement = seq("loop", opt_attributes_no_if, req(seq("{", repeat(() => statement), opt(tagScope(seq(opt_attributes, "continuing", opt_attributes_no_if, "{", repeat(() => statement), tagScope(opt(seq(opt_attributes, seq("break", "if", expression, ";")).collect(statementCollect))), "}").collect(statementCollect).collect(scopeCollect))), "}"), "invalid loop statement")).collect(scopeCollect);
10946
- const case_selector = or("default", expression);
10947
- const switch_clause = tagScope(seq(opt_attributes, or(seq("case", withSep(",", case_selector, { requireOne: true }), opt(":"), compound_statement), seq("default", opt(":"), compound_statement)).collect(switchClauseCollect)));
10948
- const switch_body = seq(opt_attributes, "{", repeatPlus(switch_clause), "}");
10949
- const switch_statement = seq("switch", expression, switch_body);
10950
- const while_statement = seq("while", expression, compound_statement);
10951
- const regular_statement = or(for_statement, if_statement, loop_statement, switch_statement, while_statement, seq("break", ";"), seq("continue", req(";", "invalid statement, expected ';'")), seq(";"), () => const_assert, seq("discard", req(";", "invalid statement, expected ';'")), seq("return", opt(expression), req(";", "invalid statement, expected ';'")), seq(fn_call, req(";", "invalid statement, expected ';'")), seq(() => variable_or_value_statement, req(";", "invalid statement, expected ';'")), seq(() => variable_updating_statement, req(";", "invalid statement, expected ';'")));
10952
- const conditional_statement = tagScope(seq(opt_attributes, regular_statement).collect(statementCollect).collect(partialScopeCollect));
10953
- const statement = or(compound_statement, tagScope(seq(opt_attributes_no_if, regular_statement)), conditional_statement);
10954
- const lhs_expression = or(simple_component_reference, seq(qualified_ident.collect(refIdent), opt(component_or_swizzle)), seq("(", () => lhs_expression, ")", opt(component_or_swizzle)), seq("&", () => lhs_expression), seq("*", () => lhs_expression));
10955
- const variable_or_value_statement = tagScope(or(local_variable_decl, seq("const", req_optionally_typed_ident, req("=", "invalid const declaration, expected '='"), expression), seq("let", req_optionally_typed_ident, req("=", "invalid let declaration, expected '='"), expression)));
10956
- const variable_updating_statement = or(seq(lhs_expression, or("=", "<<=", ">>=", "%=", "&=", "*=", "+=", "-=", "/=", "^=", "|="), expression), seq(lhs_expression, or("++", "--")), seq("_", "=", expression));
10957
- const fn_decl = seq(tagScope(opt_attributes.collect((cc) => cc.tags.attribute || [])).ctag("fn_attributes"), text("fn"), req(fnNameDecl, "invalid fn, expected function name"), seq(req(fnParamList, "invalid fn, expected function parameters").collect(scopeCollectNoIf, "header_scope"), opt(seq("->", opt_attributes.collect((cc) => cc.tags.attribute, "return_attributes"), type_specifier.ctag("return_type").collect(scopeCollectNoIf, "return_scope"))), req(unscoped_compound_statement, "invalid fn, expected function body").ctag("body_statement").collect(scopeCollectNoIf, "body_scope"))).collect(partialScopeCollect, "fn_partial_scope").collect(fnCollect);
10958
- const global_value_decl = or(seq(opt_attributes, "override", global_ident, seq(opt(seq("=", expression.collect(scopeCollectNoIf, "decl_scope")))), ";").collect(collectVarLike("override")), seq(opt_attributes, "const", global_ident, "=", seq(expression).collect(scopeCollectNoIf, "decl_scope"), ";").collect(collectVarLike("const"))).collect(partialScopeCollect);
10959
- const global_alias = seq(weslExtension(opt_attributes).collect((cc) => cc.tags.attribute, "attributes"), "alias", req(word, "invalid alias, expected name").collect(globalDeclCollect, "alias_name"), req("=", "invalid alias, expected '='"), req(type_specifier, "invalid alias, expected type").collect(scopeCollect, "alias_scope"), req(";", "invalid alias, expected ';'")).collect(aliasCollect);
10960
- const const_assert = tagScope(seq(opt_attributes, "const_assert", req(expression, "invalid const_assert, expected expression"), req(";", "invalid statement, expected ';'")).collect(assertCollect)).ctag("const_assert");
10961
- const global_directive = tagScope(seq(opt_attributes, terminated(or(preceded("diagnostic", diagnostic_control).map(makeDiagnosticDirective), preceded("enable", name_list).map(makeEnableDirective), preceded("requires", name_list).map(makeRequiresDirective)).ptag("directive"), ";")).collect(directiveCollect));
10962
- const global_decl = tagScope(or(fn_decl, global_variable_decl, global_value_decl, ";", global_alias, const_assert.collect(globalAssertCollect), struct_decl));
10963
- const weslRoot = seq(weslExtension(weslImports), repeat(global_directive), repeat(global_decl), req(eof(), "invalid WESL, expected EOF")).collect(collectModule, "collectModule");
10964
- function makeDiagnosticDirective([severity, rule]) {
10965
- return {
10966
- kind: "diagnostic",
10967
- severity,
10968
- rule
10969
- };
10970
- }
10971
- function makeEnableDirective(extensions) {
10972
- return {
10973
- kind: "enable",
10974
- extensions
10975
- };
10976
- }
10977
- function makeRequiresDirective(extensions) {
10978
- return {
10979
- kind: "requires",
10980
- extensions
10981
- };
10982
- }
10983
- function makeStandardAttribute([name$1, params]) {
10984
- return {
10985
- kind: "@attribute",
10986
- name: name$1,
10987
- params
10988
- };
10989
- }
10990
- function makeInterpolateAttribute(params) {
10991
- return {
10992
- kind: "@interpolate",
10993
- params
10994
- };
10995
- }
10996
- function makeBuiltinAttribute(param) {
10997
- return {
10998
- kind: "@builtin",
10999
- param
11000
- };
11001
- }
11002
- function makeDiagnosticAttribute([severity, rule]) {
11003
- return {
11004
- kind: "@diagnostic",
11005
- severity,
11006
- rule
11007
- };
11008
- }
11009
- function makeName(token$1) {
11010
- return {
11011
- kind: "name",
11012
- name: token$1.text,
11013
- start: token$1.span[0],
11014
- end: token$1.span[1]
11015
- };
11016
- }
11017
- if (tracing) {
11018
- const names = {
11019
- name,
11020
- diagnostic_rule_name,
11021
- diagnostic_control,
11022
- name_list,
11023
- special_attribute,
11024
- if_attribute,
11025
- elif_attribute,
11026
- else_attribute,
11027
- normal_attribute,
11028
- attribute_argument_list,
11029
- attribute_no_if,
11030
- attribute_incl_if,
11031
- opt_attributes,
11032
- opt_attributes_no_if,
11033
- globalTypeNameDecl,
11034
- fnNameDecl,
11035
- optionally_typed_ident,
11036
- req_optionally_typed_ident,
11037
- global_ident,
11038
- struct_member,
11039
- struct_decl,
11040
- fn_call,
11041
- fnParam,
11042
- fnParamList,
11043
- local_variable_decl,
11044
- global_variable_decl,
11045
- unscoped_compound_statement,
11046
- compound_statement,
11047
- for_init,
11048
- for_update,
11049
- for_statement,
11050
- if_statement,
11051
- loop_statement,
11052
- case_selector,
11053
- switch_clause,
11054
- switch_body,
11055
- switch_statement,
11056
- while_statement,
11057
- regular_statement,
11058
- conditional_statement,
11059
- statement,
11060
- lhs_expression,
11061
- variable_or_value_statement,
11062
- variable_updating_statement,
11063
- fn_decl,
11064
- global_value_decl,
11065
- global_alias,
11066
- const_assert,
11067
- global_directive,
11068
- global_decl,
11069
- weslRoot,
11070
- qualified_ident,
11071
- word
11072
- };
11073
- Object.entries(names).forEach(([name$1, parser$1]) => {
11074
- parser$1.setTraceName(name$1);
11075
- });
11076
- }
11077
-
11078
- //#endregion
11079
- //#region ../wesl/src/ParseWESL.ts
11080
- /**
11081
- * An error when parsing WESL fails. Designed to be human-readable.
11082
- */
11083
- var WeslParseError$1 = class extends Error {
11084
- span;
11085
- src;
11086
- constructor(opts) {
11087
- const source = opts.src.src;
11088
- const [lineNum, linePos] = offsetToLineNumber(opts.cause.span[0], source);
11089
- let message = `${opts.src.debugFilePath}:${lineNum}:${linePos}`;
11090
- message += ` error: ${opts.cause.message}\n`;
11091
- message += errorHighlight(source, opts.cause.span).join("\n");
11092
- super(message, { cause: opts.cause });
11093
- this.span = opts.cause.span;
11094
- this.src = opts.src;
11095
- }
11096
- };
11097
- /** Parse a WESL file. Throws on error. */
11098
- function parseSrcModule(srcModule) {
11099
- const stream$1 = new WeslStream(srcModule.src);
11100
- const appState = blankWeslParseState(srcModule);
11101
- const init = {
11102
- stream: stream$1,
11103
- appState
11104
- };
11105
- try {
11106
- if (weslRoot.parse(init) === null) throw new Error("parseWESL failed");
11107
- } catch (e) {
11108
- if (e instanceof ParseError) {
11109
- const [lineNumber, lineColumn] = offsetToLineNumber(e.span[0], srcModule.src);
11110
- const error = new WeslParseError$1({
11111
- cause: e,
11112
- src: srcModule
11113
- });
11114
- throwClickableError({
11115
- url: srcModule.debugFilePath,
11116
- text: srcModule.src,
11117
- error,
11118
- lineNumber,
11119
- lineColumn,
11120
- length: e.span[1] - e.span[0]
11121
- });
11122
- } else throw e;
11123
- }
11124
- return appState.stable;
11125
- }
11126
- function blankWeslParseState(srcModule) {
11127
- const rootScope = emptyScope(null);
11128
- return {
11129
- context: {
11130
- scope: rootScope,
11131
- openElems: []
11132
- },
11133
- stable: {
11134
- srcModule,
11135
- imports: [],
11136
- rootScope,
11137
- moduleElem: null
11138
- }
11139
- };
11140
- }
11141
-
11142
- //#endregion
11143
- //#region ../wesl/src/PathUtil.ts
11144
- /** simplistic path manipulation utilities */
11145
- /** return path with ./ and foo/.. elements removed */
11146
- function normalize(path$2) {
11147
- const noDots = path$2.split("/").filter((s) => s !== ".");
11148
- const noDbl = [];
11149
- noDots.forEach((s) => {
11150
- if (s !== "") if (s === ".." && noDbl.length && noDbl[noDbl.length - 1] !== "..") noDbl.pop();
11151
- else noDbl.push(s);
11152
- });
11153
- return noDbl.join("/");
11154
- }
11155
- /** return path w/o a suffix.
11156
- * e.g. /foo/bar.wgsl => /foo/bar */
11157
- function noSuffix(path$2) {
11158
- const lastSlash = path$2.lastIndexOf("/");
11159
- const lastStart = lastSlash === -1 ? 0 : lastSlash + 1;
11160
- const suffix = path$2.indexOf(".", lastStart);
11161
- const suffixStart = suffix === -1 ? path$2.length : suffix;
11162
- return path$2.slice(0, suffixStart);
11163
- }
11164
-
11165
- //#endregion
11166
- //#region ../wesl/src/ParsedRegistry.ts
11167
- function parsedRegistry$1() {
11168
- resetScopeIds();
11169
- return { modules: {} };
9849
+ //#region ../wesl-tooling/src/Version.ts
9850
+ /** Read package.json from a directory.
9851
+ * @param projectDir - file:// URL string to directory containing package.json
9852
+ * @returns the parsed package.json contents */
9853
+ async function readPackageJson(projectDir) {
9854
+ const baseUrl = projectDir.endsWith("/") ? projectDir : `${projectDir}/`;
9855
+ return (await import(new URL("package.json", baseUrl).href, { with: { type: "json" } })).default;
11170
9856
  }
11171
9857
  /**
11172
- * @param srcFiles map of source strings by file path
11173
- * key is '/' separated relative path (relative to srcRoot, not absolute file path )
11174
- * value is wesl source string
11175
- * @param registry add parsed modules to this registry
11176
- * @param packageName name of package
9858
+ * @param projectDir - file:// URL string to directory containing package.json
9859
+ * @returns the 'version' field from the package.json in the `projectDir`
11177
9860
  */
11178
- function parseIntoRegistry$1(srcFiles, registry, packageName = "package", debugWeslRoot) {
11179
- let weslRoot$1 = debugWeslRoot;
11180
- if (weslRoot$1 === void 0) weslRoot$1 = "";
11181
- else if (!weslRoot$1.endsWith("/")) weslRoot$1 += "/";
11182
- Object.entries(srcFiles).map(([filePath, src]) => {
11183
- return {
11184
- modulePath: fileToModulePath(filePath, packageName),
11185
- debugFilePath: weslRoot$1 + filePath,
11186
- src
11187
- };
11188
- }).forEach((mod) => {
11189
- const parsed = parseSrcModule(mod);
11190
- if (registry.modules[mod.modulePath]) return;
11191
- registry.modules[mod.modulePath] = parsed;
11192
- });
11193
- }
11194
- const libRegex = /^lib\.w[eg]sl$/i;
11195
- /** convert a file path (./foo/bar.wesl)
11196
- * to a module path (package::foo::bar) */
11197
- function fileToModulePath(filePath, packageName) {
11198
- if (filePath.includes("::")) return filePath;
11199
- if (packageName !== "package" && libRegex.test(filePath)) return packageName;
11200
- const moduleSuffix = noSuffix(normalize(filePath)).replaceAll("/", "::");
11201
- return packageName + "::" + moduleSuffix;
9861
+ async function versionFromPackageJson(projectDir) {
9862
+ return (await readPackageJson(projectDir)).version;
11202
9863
  }
11203
9864
 
11204
9865
  //#endregion
@@ -11208,7 +9869,8 @@ async function cli(rawArgs) {
11208
9869
  await linkNormally(await parseArgs(rawArgs));
11209
9870
  }
11210
9871
  async function parseArgs(args) {
11211
- const appVersion = await versionFromPackageJson(new URL("..", import.meta.url));
9872
+ const toolDir = new URL("..", import.meta.url).href;
9873
+ const appVersion = await versionFromPackageJson(toolDir);
11212
9874
  return yargs(args).version(appVersion).command("$0 [module]", false, (yargs$1) => {
11213
9875
  yargs$1.positional("module", {
11214
9876
  type: "string",
@@ -11261,20 +9923,15 @@ async function linkNormally(argv) {
11261
9923
  conditions
11262
9924
  })).dest);
11263
9925
  if (argv.details) {
11264
- const registry = parsedRegistry$1();
11265
- try {
11266
- parseIntoRegistry$1(weslSrc, registry, "package");
11267
- } catch (e) {
11268
- console.error(e);
11269
- }
11270
- Object.entries(registry.modules).forEach(([modulePath, ast]) => {
9926
+ const resolver = new RecordResolver(weslSrc);
9927
+ for (const [modulePath, ast] of resolver.allModules()) {
11271
9928
  log(`---\n${modulePath}`);
11272
9929
  log(`\n->ast`);
11273
9930
  log(astToString(ast.moduleElem));
11274
9931
  log(`\n->scope`);
11275
9932
  log(scopeToString(ast.rootScope));
11276
9933
  log();
11277
- });
9934
+ }
11278
9935
  }
11279
9936
  }
11280
9937
  /** load the weslbundle containing the root module (if we haven't already loaded it) */