wesl 0.6.49 → 0.7.1

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 (94) hide show
  1. package/dist/index.d.ts +269 -215
  2. package/dist/index.js +2911 -1539
  3. package/package.json +6 -8
  4. package/src/AbstractElems.ts +81 -81
  5. package/src/Assertions.ts +5 -5
  6. package/src/BindIdents.ts +192 -306
  7. package/src/ClickableError.ts +3 -2
  8. package/src/Conditions.ts +2 -2
  9. package/src/LinkedWesl.ts +1 -1
  10. package/src/Linker.ts +4 -3
  11. package/src/LinkerUtil.ts +1 -1
  12. package/src/Logging.ts +165 -0
  13. package/src/LowerAndEmit.ts +278 -110
  14. package/src/ModuleResolver.ts +15 -25
  15. package/src/ParseError.ts +9 -0
  16. package/src/ParseWESL.ts +30 -94
  17. package/src/RawEmit.ts +1 -4
  18. package/src/Reflection.ts +1 -1
  19. package/src/Scope.ts +3 -0
  20. package/src/Span.ts +2 -0
  21. package/src/SrcMap.ts +208 -0
  22. package/src/Stream.ts +30 -0
  23. package/src/TransformBindingStructs.ts +2 -2
  24. package/src/Util.ts +1 -1
  25. package/src/debug/ASTtoString.ts +84 -135
  26. package/src/discovery/FindUnboundIdents.ts +14 -5
  27. package/src/index.ts +4 -0
  28. package/src/parse/ContentsHelpers.ts +70 -0
  29. package/src/parse/ExpressionUtil.ts +121 -0
  30. package/src/parse/Keywords.ts +12 -12
  31. package/src/parse/OperatorBinding.ts +146 -0
  32. package/src/parse/ParseAttribute.ts +272 -0
  33. package/src/parse/ParseCall.ts +77 -0
  34. package/src/parse/ParseControlFlow.ts +129 -0
  35. package/src/parse/ParseDirective.ts +105 -0
  36. package/src/parse/ParseExpression.ts +288 -0
  37. package/src/parse/ParseFn.ts +151 -0
  38. package/src/parse/ParseGlobalVar.ts +131 -0
  39. package/src/parse/ParseIdent.ts +77 -0
  40. package/src/parse/ParseImport.ts +160 -0
  41. package/src/parse/ParseLocalVar.ts +69 -0
  42. package/src/parse/ParseLoop.ts +112 -0
  43. package/src/parse/ParseModule.ts +116 -0
  44. package/src/parse/ParseSimpleStatement.ts +162 -0
  45. package/src/parse/ParseStatement.ts +215 -0
  46. package/src/parse/ParseStruct.ts +89 -0
  47. package/src/parse/ParseType.ts +71 -0
  48. package/src/parse/ParseUtil.ts +174 -0
  49. package/src/parse/ParseValueDeclaration.ts +130 -0
  50. package/src/parse/ParseWesl.ts +51 -0
  51. package/src/parse/ParsingContext.ts +93 -0
  52. package/src/parse/WeslStream.ts +63 -20
  53. package/src/parse/stream/CachingStream.ts +48 -0
  54. package/src/parse/stream/MatchersStream.ts +85 -0
  55. package/src/parse/stream/RegexHelpers.ts +38 -0
  56. package/src/test/BevyLink.test.ts +100 -0
  57. package/src/test/BindStdTypes.test.ts +110 -0
  58. package/src/test/{BindWESL.test.ts → BindWESLV2.test.ts} +21 -22
  59. package/src/test/BulkTests.test.ts +11 -12
  60. package/src/test/ConditionLinking.test.ts +107 -0
  61. package/src/test/ConditionalElif.test.ts +1 -13
  62. package/src/test/ConditionalTranslationCases.test.ts +5 -0
  63. package/src/test/ErrorLogging.test.ts +2 -2
  64. package/src/test/ImportCasesV2.test.ts +63 -0
  65. package/src/test/LinkFails.test.ts +69 -0
  66. package/src/test/LinkPackage.test.ts +1 -1
  67. package/src/test/Linker.test.ts +75 -2
  68. package/src/test/LogCatcher.ts +53 -0
  69. package/src/test/Mangling.test.ts +1 -1
  70. package/src/test/ParseComments.test.ts +1 -2
  71. package/src/test/{ParseConditions.test.ts → ParseConditionsV2.test.ts} +57 -49
  72. package/src/test/ParseErrorV2.test.ts +73 -0
  73. package/src/test/{ParseWESL.test.ts → ParseWeslV2.test.ts} +288 -370
  74. package/src/test/{ScopeWESL.test.ts → ScopeWESLV2.test.ts} +205 -176
  75. package/src/test/TestLink.ts +51 -51
  76. package/src/test/TestSetup.ts +9 -3
  77. package/src/test/TestUtil.ts +47 -77
  78. package/src/test/TrimmedMatch.ts +40 -0
  79. package/src/test/VirtualModules.test.ts +33 -2
  80. package/src/test/WeslDevice.test.ts +9 -2
  81. package/src/test/__snapshots__/ParseWeslV2.test.ts.snap +67 -0
  82. package/src/test-util.ts +7 -0
  83. package/src/WESLCollect.ts +0 -656
  84. package/src/parse/AttributeGrammar.ts +0 -232
  85. package/src/parse/ImportGrammar.ts +0 -195
  86. package/src/parse/WeslBaseGrammar.ts +0 -11
  87. package/src/parse/WeslExpression.ts +0 -231
  88. package/src/parse/WeslGrammar.ts +0 -739
  89. package/src/test/Expression.test.ts +0 -22
  90. package/src/test/ImportSyntaxCases.test.ts +0 -24
  91. package/src/test/ParseError.test.ts +0 -45
  92. package/src/test/Reflection.test.ts +0 -176
  93. package/src/test/TransformBindingStructs.test.ts +0 -238
  94. /package/src/test/{ParseElif.test.ts → ParseElifV2.test.ts} +0 -0
@@ -1,5 +1,5 @@
1
- import { srcLog, tracing } from "mini-parse";
2
1
  import type { DeclIdentElem, RefIdent, RefIdentElem } from "wesl";
2
+ import { debug, srcLog } from "./Logging.ts";
3
3
  import { offsetToLineNumber } from "./Util.ts";
4
4
  import { encodeVlq } from "./vlq/vlq.ts";
5
5
 
@@ -26,6 +26,7 @@ export interface ClickableErrorParams {
26
26
  /** Throw an error with an embedded source map so that browser users can
27
27
  * click on the error in the browser debug console and see the wesl source code. */
28
28
  export function throwClickableError(params: ClickableErrorParams): void {
29
+ if (!debug) throw params.error; // skip source map generation in prod
29
30
  const { url, text, lineNumber, lineColumn, length, error } = params;
30
31
 
31
32
  // Based on https://stackoverflow.com/questions/65274147/sourceurl-for-css
@@ -87,7 +88,7 @@ export function throwClickableError(params: ClickableErrorParams): void {
87
88
  Error.stackTraceLimit = oldLimit;
88
89
  }
89
90
  error.message = "";
90
- if (tracing) e.cause = error; // users don't want to see this, but WESL developers might
91
+ if (debug) e.cause = error; // users don't want to see this, but WESL developers might
91
92
  throw e;
92
93
  }
93
94
  }
package/src/Conditions.ts CHANGED
@@ -74,8 +74,8 @@ function evaluateIfExpression(
74
74
  return value === "true";
75
75
  } else if (kind === "parenthesized-expression") {
76
76
  return evaluateIfExpression(expression.expression, conditions);
77
- } else if (kind === "translate-time-feature") {
78
- return conditions[expression.name] ?? false;
77
+ } else if (kind === "ref") {
78
+ return conditions[expression.ident.originalName] ?? false;
79
79
  } else {
80
80
  throw new Error(`unexpected @if expression ${JSON.stringify(expression)}`);
81
81
  }
package/src/LinkedWesl.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { SrcMap } from "mini-parse";
2
1
  import { assertThatDebug } from "./Assertions.ts";
2
+ import type { SrcMap } from "./SrcMap.ts";
3
3
  import { errorHighlight, offsetToLineNumber } from "./Util.ts";
4
4
  import type { WeslDevice } from "./WeslDevice";
5
5
 
package/src/Linker.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { type SrcMap, SrcMapBuilder, tracing } from "mini-parse";
2
1
  import type { AbstractElem, ModuleElem } from "./AbstractElems.ts";
3
2
  import {
4
3
  bindIdents,
@@ -6,6 +5,7 @@ import {
6
5
  type VirtualLibrarySet,
7
6
  } from "./BindIdents.ts";
8
7
  import { LinkedWesl } from "./LinkedWesl.ts";
8
+ import { debug } from "./Logging.ts";
9
9
  import { lowerAndEmit } from "./LowerAndEmit.ts";
10
10
  import type { ManglerFn } from "./Mangler.ts";
11
11
  import {
@@ -16,6 +16,7 @@ import {
16
16
  } from "./ModuleResolver.ts";
17
17
  import type { WeslAST } from "./ParseWESL.ts";
18
18
  import type { Conditions, DeclIdent, SrcModule } from "./Scope.ts";
19
+ import { type SrcMap, SrcMapBuilder } from "./SrcMap.ts";
19
20
  import { filterMap, mapValues } from "./Util.ts";
20
21
  import type { WeslBundle } from "./WeslBundle.ts";
21
22
 
@@ -129,7 +130,7 @@ export function _linkSync(params: LinkParams): SrcMap {
129
130
  const finalResolver =
130
131
  resolvers.length === 1 ? resolvers[0] : new CompositeResolver(resolvers);
131
132
 
132
- return linkRegistry({ resolver: finalResolver, ...params });
133
+ return linkRegistry({ ...params, resolver: finalResolver });
133
134
  }
134
135
 
135
136
  function createLibraryResolvers(
@@ -246,7 +247,7 @@ function getRootModule(
246
247
  ): WeslAST {
247
248
  const rootAst = resolver.resolveModule(modulePath);
248
249
  if (!rootAst) {
249
- if (tracing) {
250
+ if (debug) {
250
251
  console.log(
251
252
  `root module not found: ${modulePath} (from ${rootModuleName})`,
252
253
  );
package/src/LinkerUtil.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { srcLog } from "mini-parse";
2
1
  import type {
3
2
  AbstractElem,
4
3
  ContainerElem,
5
4
  DeclIdentElem,
6
5
  RefIdentElem,
7
6
  } from "./AbstractElems.ts";
7
+ import { srcLog } from "./Logging.ts";
8
8
 
9
9
  export function visitAst(
10
10
  elem: AbstractElem,
package/src/Logging.ts ADDED
@@ -0,0 +1,165 @@
1
+ import type { SrcMap, SrcWithPath } from "./SrcMap.ts";
2
+
3
+ /** base logger (can be overridden to a capturing logger for tests) */
4
+ export let log = console.log;
5
+
6
+ /** enable debug assertions and verbose error messages (set false via bundler for smaller builds) */
7
+ export const debug = true;
8
+
9
+ /** enable user-facing validation like operator binding rules (set false via bundler for smaller builds) */
10
+ export const validation = true;
11
+
12
+ /** use temporary logger for tests */
13
+ export function withLogger<T>(logFn: typeof console.log, fn: () => T): T {
14
+ const orig = log;
15
+ try {
16
+ log = logFn;
17
+ return fn();
18
+ } finally {
19
+ log = orig;
20
+ }
21
+ }
22
+
23
+ /** use temporary logger for async tests */
24
+ export async function withLoggerAsync<T>(
25
+ logFn: typeof console.log,
26
+ fn: () => Promise<T>,
27
+ ): Promise<T> {
28
+ const orig = log;
29
+ try {
30
+ log = logFn;
31
+ return await fn();
32
+ } finally {
33
+ log = orig;
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Log a message along with the source line and a caret indicating the error position.
39
+ * @param pos is the position in the source string, or if src is a SrcMap,
40
+ * then pos is the position in the dest (e.g. preprocessed) text
41
+ */
42
+ export function srcLog(
43
+ src: string | SrcMap,
44
+ pos: number | [number, number],
45
+ ...msgs: any[]
46
+ ): void {
47
+ if (typeof src === "string") {
48
+ logInternalSrc(log, src, pos, ...msgs);
49
+ return;
50
+ }
51
+ const { src: mappedSrc, positions } = mapSrcPositions(src, pos);
52
+ logInternalSrc(log, mappedSrc.text, positions, ...msgs);
53
+ }
54
+
55
+ interface SrcPositions {
56
+ positions: number | [number, number];
57
+ src: SrcWithPath;
58
+ }
59
+
60
+ function mapSrcPositions(
61
+ srcMap: SrcMap,
62
+ destPos: number | [number, number],
63
+ ): SrcPositions {
64
+ const srcPos = srcMap.mapPositions(...[destPos].flat());
65
+ const { src } = srcPos[0];
66
+
67
+ let positions: [number, number] | number;
68
+ if (srcPos[1]?.src?.path === src.path && srcPos[1]?.src?.text === src.text) {
69
+ positions = srcPos.map(p => p.position) as [number, number];
70
+ } else {
71
+ positions = srcPos[0].position;
72
+ }
73
+
74
+ return { src, positions };
75
+ }
76
+
77
+ function logInternalSrc(
78
+ logFn: typeof console.log,
79
+ src: string,
80
+ pos: number | [number, number],
81
+ ...msgs: any[]
82
+ ): void {
83
+ logFn(...msgs);
84
+ const { line, lineNum, linePos, linePos2 } = srcLine(src, pos);
85
+ logFn(line, ` Ln ${lineNum}`);
86
+ const caret = carets(linePos, linePos2);
87
+ logFn(caret);
88
+ }
89
+
90
+ function carets(linePos: number, linePos2?: number): string {
91
+ const indent = " ".repeat(linePos);
92
+ const numCarets = linePos2 ? linePos2 - linePos : 1;
93
+ const caretStr = "^".repeat(numCarets);
94
+ return indent + caretStr;
95
+ }
96
+
97
+ // map from src strings to line start positions
98
+ const startCache = new Map<string, number[]>();
99
+
100
+ interface SrcLine {
101
+ /** src line w/o newline */
102
+ line: string;
103
+ /** requested position relative to line start */
104
+ linePos: number;
105
+ /** requested position2 relative to line start */
106
+ linePos2?: number;
107
+ /** line number in the src (first line is #1) */
108
+ lineNum: number;
109
+ }
110
+
111
+ /** return the line in the src containing a given character position */
112
+ export function srcLine(
113
+ src: string,
114
+ position: number | [number, number],
115
+ ): SrcLine {
116
+ let pos: number;
117
+ let pos2: number | undefined;
118
+ if (typeof position === "number") {
119
+ pos = position;
120
+ } else {
121
+ [pos, pos2] = position;
122
+ }
123
+ const starts = getStarts(src);
124
+
125
+ let start = 0;
126
+ let end = starts.length - 1;
127
+
128
+ // short circuit search if pos is after last line start
129
+ if (pos >= starts[end]) {
130
+ start = end;
131
+ }
132
+
133
+ // binary search to find start,end positions that surround provided pos
134
+ while (start + 1 < end) {
135
+ const mid = (start + end) >> 1;
136
+ if (pos >= starts[mid]) {
137
+ start = mid;
138
+ } else {
139
+ end = mid;
140
+ }
141
+ }
142
+
143
+ let linePos2: number | undefined;
144
+ if (pos2 !== undefined && pos2 >= starts[start] && pos2 < starts[end]) {
145
+ linePos2 = pos2 - starts[start];
146
+ }
147
+
148
+ // get line with possible trailing newline
149
+ const lineNl = src.slice(starts[start], starts[start + 1] || src.length);
150
+
151
+ // return line without trailing newline
152
+ const line = lineNl.slice(-1) === "\n" ? lineNl.slice(0, -1) : lineNl;
153
+
154
+ return { line, linePos: pos - starts[start], linePos2, lineNum: start + 1 };
155
+ }
156
+
157
+ /** return an array of the character positions of the start of each line in the src (cached) */
158
+ function getStarts(src: string): number[] {
159
+ const found = startCache.get(src);
160
+ if (found) return found;
161
+ const starts = [...src.matchAll(/\n/g)].map(m => m.index! + 1);
162
+ starts.unshift(0);
163
+ startCache.set(src, starts);
164
+ return starts;
165
+ }