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.
- package/dist/index.d.ts +269 -215
- package/dist/index.js +2911 -1539
- package/package.json +6 -8
- package/src/AbstractElems.ts +81 -81
- package/src/Assertions.ts +5 -5
- package/src/BindIdents.ts +192 -306
- package/src/ClickableError.ts +3 -2
- package/src/Conditions.ts +2 -2
- package/src/LinkedWesl.ts +1 -1
- package/src/Linker.ts +4 -3
- package/src/LinkerUtil.ts +1 -1
- package/src/Logging.ts +165 -0
- package/src/LowerAndEmit.ts +278 -110
- package/src/ModuleResolver.ts +15 -25
- package/src/ParseError.ts +9 -0
- package/src/ParseWESL.ts +30 -94
- package/src/RawEmit.ts +1 -4
- package/src/Reflection.ts +1 -1
- package/src/Scope.ts +3 -0
- package/src/Span.ts +2 -0
- package/src/SrcMap.ts +208 -0
- package/src/Stream.ts +30 -0
- package/src/TransformBindingStructs.ts +2 -2
- package/src/Util.ts +1 -1
- package/src/debug/ASTtoString.ts +84 -135
- package/src/discovery/FindUnboundIdents.ts +14 -5
- package/src/index.ts +4 -0
- package/src/parse/ContentsHelpers.ts +70 -0
- package/src/parse/ExpressionUtil.ts +121 -0
- package/src/parse/Keywords.ts +12 -12
- package/src/parse/OperatorBinding.ts +146 -0
- package/src/parse/ParseAttribute.ts +272 -0
- package/src/parse/ParseCall.ts +77 -0
- package/src/parse/ParseControlFlow.ts +129 -0
- package/src/parse/ParseDirective.ts +105 -0
- package/src/parse/ParseExpression.ts +288 -0
- package/src/parse/ParseFn.ts +151 -0
- package/src/parse/ParseGlobalVar.ts +131 -0
- package/src/parse/ParseIdent.ts +77 -0
- package/src/parse/ParseImport.ts +160 -0
- package/src/parse/ParseLocalVar.ts +69 -0
- package/src/parse/ParseLoop.ts +112 -0
- package/src/parse/ParseModule.ts +116 -0
- package/src/parse/ParseSimpleStatement.ts +162 -0
- package/src/parse/ParseStatement.ts +215 -0
- package/src/parse/ParseStruct.ts +89 -0
- package/src/parse/ParseType.ts +71 -0
- package/src/parse/ParseUtil.ts +174 -0
- package/src/parse/ParseValueDeclaration.ts +130 -0
- package/src/parse/ParseWesl.ts +51 -0
- package/src/parse/ParsingContext.ts +93 -0
- package/src/parse/WeslStream.ts +63 -20
- package/src/parse/stream/CachingStream.ts +48 -0
- package/src/parse/stream/MatchersStream.ts +85 -0
- package/src/parse/stream/RegexHelpers.ts +38 -0
- package/src/test/BevyLink.test.ts +100 -0
- package/src/test/BindStdTypes.test.ts +110 -0
- package/src/test/{BindWESL.test.ts → BindWESLV2.test.ts} +21 -22
- package/src/test/BulkTests.test.ts +11 -12
- package/src/test/ConditionLinking.test.ts +107 -0
- package/src/test/ConditionalElif.test.ts +1 -13
- package/src/test/ConditionalTranslationCases.test.ts +5 -0
- package/src/test/ErrorLogging.test.ts +2 -2
- package/src/test/ImportCasesV2.test.ts +63 -0
- package/src/test/LinkFails.test.ts +69 -0
- package/src/test/LinkPackage.test.ts +1 -1
- package/src/test/Linker.test.ts +75 -2
- package/src/test/LogCatcher.ts +53 -0
- package/src/test/Mangling.test.ts +1 -1
- package/src/test/ParseComments.test.ts +1 -2
- package/src/test/{ParseConditions.test.ts → ParseConditionsV2.test.ts} +57 -49
- package/src/test/ParseErrorV2.test.ts +73 -0
- package/src/test/{ParseWESL.test.ts → ParseWeslV2.test.ts} +288 -370
- package/src/test/{ScopeWESL.test.ts → ScopeWESLV2.test.ts} +205 -176
- package/src/test/TestLink.ts +51 -51
- package/src/test/TestSetup.ts +9 -3
- package/src/test/TestUtil.ts +47 -77
- package/src/test/TrimmedMatch.ts +40 -0
- package/src/test/VirtualModules.test.ts +33 -2
- package/src/test/WeslDevice.test.ts +9 -2
- package/src/test/__snapshots__/ParseWeslV2.test.ts.snap +67 -0
- package/src/test-util.ts +7 -0
- package/src/WESLCollect.ts +0 -656
- package/src/parse/AttributeGrammar.ts +0 -232
- package/src/parse/ImportGrammar.ts +0 -195
- package/src/parse/WeslBaseGrammar.ts +0 -11
- package/src/parse/WeslExpression.ts +0 -231
- package/src/parse/WeslGrammar.ts +0 -739
- package/src/test/Expression.test.ts +0 -22
- package/src/test/ImportSyntaxCases.test.ts +0 -24
- package/src/test/ParseError.test.ts +0 -45
- package/src/test/Reflection.test.ts +0 -176
- package/src/test/TransformBindingStructs.test.ts +0 -238
- /package/src/test/{ParseElif.test.ts → ParseElifV2.test.ts} +0 -0
package/src/ClickableError.ts
CHANGED
|
@@ -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 (
|
|
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 === "
|
|
78
|
-
return conditions[expression.
|
|
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
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
|
|
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 (
|
|
250
|
+
if (debug) {
|
|
250
251
|
console.log(
|
|
251
252
|
`root module not found: ${modulePath} (from ${rootModuleName})`,
|
|
252
253
|
);
|
package/src/LinkerUtil.ts
CHANGED
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
|
+
}
|