wesl 0.7.27 → 0.7.28
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 +272 -126
- package/dist/index.js +1742 -1102
- package/package.json +1 -1
- package/src/AbstractElems.ts +263 -81
- package/src/Linker.ts +14 -2
- package/src/LinkerUtil.ts +141 -7
- package/src/LowerAndEmit.ts +660 -304
- package/src/ModuleResolver.ts +15 -4
- package/src/ParseWESL.ts +21 -33
- package/src/SrcMap.ts +7 -19
- package/src/debug/ASTtoString.ts +92 -76
- package/src/index.ts +1 -1
- package/src/parse/AttachComments.ts +289 -0
- package/src/parse/ExpressionUtil.ts +3 -3
- package/src/parse/ParseAttribute.ts +49 -71
- package/src/parse/ParseCall.ts +3 -4
- package/src/parse/ParseControlFlow.ts +100 -56
- package/src/parse/ParseDirective.ts +9 -8
- package/src/parse/ParseDoBlock.ts +63 -0
- package/src/parse/ParseExpression.ts +11 -10
- package/src/parse/ParseFn.ts +11 -33
- package/src/parse/ParseGlobalVar.ts +36 -27
- package/src/parse/ParseIdent.ts +4 -5
- package/src/parse/ParseLocalVar.ts +16 -12
- package/src/parse/ParseLoop.ts +76 -39
- package/src/parse/ParseModule.ts +65 -19
- package/src/parse/ParseSimpleStatement.ts +112 -66
- package/src/parse/ParseStatement.ts +39 -66
- package/src/parse/ParseStruct.ts +8 -22
- package/src/parse/ParseType.ts +10 -13
- package/src/parse/ParseUtil.ts +26 -12
- package/src/parse/ParseValueDeclaration.ts +18 -31
- package/src/parse/ParseWesl.ts +11 -14
- package/src/parse/ParsingContext.ts +11 -9
- package/src/parse/WeslStream.ts +138 -121
- package/src/parse/stream/RegexMatchers.ts +45 -0
- package/src/parse/stream/WeslLexer.ts +249 -0
- package/src/test/BevyLink.test.ts +17 -10
- package/src/test/ConditionalElif.test.ts +4 -2
- package/src/test/DeclCommentEmit.test.ts +122 -0
- package/src/test/DoBlock.test.ts +164 -0
- package/src/test/FilterValidElements.test.ts +4 -6
- package/src/test/Linker.test.ts +23 -7
- package/src/test/Mangling.test.ts +8 -4
- package/src/test/ParseComments.test.ts +234 -6
- package/src/test/ParseConditionsV2.test.ts +47 -175
- package/src/test/ParseElifV2.test.ts +12 -33
- package/src/test/ParseErrorV2.test.ts +0 -0
- package/src/test/ParseWeslV2.test.ts +247 -626
- package/src/test/StatementEmit.test.ts +143 -0
- package/src/test/StripWesl.ts +24 -3
- package/src/test/TestLink.ts +19 -3
- package/src/test/TestUtil.ts +18 -8
- package/src/test/Tokenizer.test.ts +96 -0
- package/src/test/__snapshots__/ParseWeslV2.test.ts.snap +10 -42
- package/src/RawEmit.ts +0 -103
- package/src/Reflection.ts +0 -336
- package/src/TransformBindingStructs.ts +0 -320
- package/src/parse/ContentsHelpers.ts +0 -70
- package/src/parse/stream/CachingStream.ts +0 -48
- package/src/parse/stream/MatchersStream.ts +0 -85
package/dist/index.d.ts
CHANGED
|
@@ -58,17 +58,42 @@ interface TypedToken<Kind extends string> extends Token {
|
|
|
58
58
|
//#region src/parse/WeslStream.d.ts
|
|
59
59
|
type WeslTokenKind = "word" | "keyword" | "number" | "symbol";
|
|
60
60
|
type WeslToken<Kind extends WeslTokenKind = WeslTokenKind> = TypedToken<Kind>;
|
|
61
|
+
/** A comment skipped by the tokenizer, recorded as leading trivia of the next token.
|
|
62
|
+
* Line-break flags (newline/blank before) are not stored here: they are derived
|
|
63
|
+
* on demand during comment attachment, so the tokenizer hot path never counts
|
|
64
|
+
* line breaks. */
|
|
65
|
+
interface CommentTrivia {
|
|
66
|
+
style: "line" | "block";
|
|
67
|
+
/** Source range of the comment text (excluding the trailing newline of a line comment). */
|
|
68
|
+
start: number;
|
|
69
|
+
end: number;
|
|
70
|
+
}
|
|
61
71
|
/** A stream that produces WESL tokens, skipping over comments and white space */
|
|
62
72
|
declare class WeslStream implements Stream<WeslToken> {
|
|
63
73
|
private stream;
|
|
64
|
-
/** New line */
|
|
74
|
+
/** New line (stateful: scanned via lastIndex, so kept per-instance). */
|
|
65
75
|
private eolPattern;
|
|
66
76
|
private blockCommentPattern;
|
|
77
|
+
/** Comments skipped before a real token, keyed by that token's start position. */
|
|
78
|
+
private triviaByPos;
|
|
79
|
+
/** Last peeked token, so the following nextToken() skips the rescan.
|
|
80
|
+
* Never invalidated: tokenization is deterministic per position. */
|
|
81
|
+
private peeked;
|
|
67
82
|
src: string;
|
|
68
83
|
constructor(src: string);
|
|
69
84
|
checkpoint(): number;
|
|
70
85
|
reset(position: number): void;
|
|
86
|
+
/** All recorded comment runs (each a contiguous group of comments between two
|
|
87
|
+
* real tokens), in source order. Consumed by the post-parse comment pass. */
|
|
88
|
+
commentRuns(): CommentTrivia[][];
|
|
89
|
+
private recordTrivia;
|
|
90
|
+
/** Next real token (comments/blankspace skipped and recorded as trivia); null at EOF. */
|
|
71
91
|
nextToken(): WeslToken | null;
|
|
92
|
+
/** If the last peek() was at the current position, consume and return it. */
|
|
93
|
+
private usePeeked;
|
|
94
|
+
/** Skip a comment (rejecting embedded \0), advance the stream past it,
|
|
95
|
+
* and return it as trivia. */
|
|
96
|
+
private consumeComment;
|
|
72
97
|
/** Peek at the next token without consuming it */
|
|
73
98
|
peek(): WeslToken | null;
|
|
74
99
|
/** Consume token if text matches, otherwise leave position unchanged */
|
|
@@ -79,7 +104,10 @@ declare class WeslStream implements Stream<WeslToken> {
|
|
|
79
104
|
nextIf(predicate: (token: WeslToken) => boolean): WeslToken | null;
|
|
80
105
|
/** Match a sequence of tokens by text. Resets and returns null if any fails. */
|
|
81
106
|
matchSequence(...texts: string[]): WeslToken[] | null;
|
|
82
|
-
|
|
107
|
+
/** End position of a comment opened by a commentStart token. */
|
|
108
|
+
private commentEnd;
|
|
109
|
+
/** End of a line comment: the start of the next line break (or end of file). */
|
|
110
|
+
private lineCommentEnd;
|
|
83
111
|
private skipBlockComment;
|
|
84
112
|
/**
|
|
85
113
|
* Only matches the `<` token if it is a template
|
|
@@ -89,9 +117,14 @@ declare class WeslStream implements Stream<WeslToken> {
|
|
|
89
117
|
nextTemplateStartToken(): (WeslToken & {
|
|
90
118
|
kind: "symbol";
|
|
91
119
|
}) | null;
|
|
120
|
+
/** Match a template-closing `>`, splitting it off a `>>`/`>=`/`>>=` token when needed. */
|
|
92
121
|
nextTemplateEndToken(): (WeslToken & {
|
|
93
122
|
kind: "symbol";
|
|
94
123
|
}) | null;
|
|
124
|
+
/** Next symbol from the raw stream, skipping comment bodies (so symbols
|
|
125
|
+
* inside comments don't count) and non-symbol tokens; null at EOF. */
|
|
126
|
+
private nextRawSymbol;
|
|
127
|
+
/** Template-list discovery: scan forward from `<` for a balanced closing `>`. */
|
|
95
128
|
private isTemplateStart;
|
|
96
129
|
/**
|
|
97
130
|
* Call this after consuming an opening bracket.
|
|
@@ -101,14 +134,17 @@ declare class WeslStream implements Stream<WeslToken> {
|
|
|
101
134
|
}
|
|
102
135
|
//#endregion
|
|
103
136
|
//#region src/parse/ParsingContext.d.ts
|
|
137
|
+
/** Opt-in toggles for not-yet-spec'd WESL/WGSL features (for prototyping). */
|
|
138
|
+
interface WeslExtensions {
|
|
139
|
+
/** Parse `do name(...) { ... }` blocks. */
|
|
140
|
+
doBlocks?: boolean;
|
|
141
|
+
}
|
|
104
142
|
interface ParseOptions {
|
|
105
|
-
/**
|
|
106
|
-
|
|
143
|
+
/** Enable parsing of experimental, not-yet-spec'd syntax extensions. */
|
|
144
|
+
weslExtensions?: WeslExtensions;
|
|
107
145
|
}
|
|
108
146
|
//#endregion
|
|
109
147
|
//#region src/ParseWESL.d.ts
|
|
110
|
-
/** Partial element being constructed during parsing. */
|
|
111
|
-
type OpenElem<T extends ContainerElem = ContainerElem> = Pick<T, "kind" | "contents">;
|
|
112
148
|
/**
|
|
113
149
|
* Result of parsing one WESL module (e.g., one .wesl file).
|
|
114
150
|
*
|
|
@@ -128,6 +164,8 @@ interface WeslAST {
|
|
|
128
164
|
imports: ImportStatement[];
|
|
129
165
|
/** Module level const_assert statements. */
|
|
130
166
|
moduleAsserts?: ConstAssertElem[];
|
|
167
|
+
/** Parse options used to produce this AST (so re-parsing preserves them). */
|
|
168
|
+
parseOptions?: ParseOptions;
|
|
131
169
|
}
|
|
132
170
|
/** Extended AST with cached flattened imports. */
|
|
133
171
|
interface BindingAST extends WeslAST {
|
|
@@ -144,7 +182,6 @@ type StableState = WeslAST;
|
|
|
144
182
|
/** Unstable values used during parse collection. */
|
|
145
183
|
interface WeslParseContext {
|
|
146
184
|
scope: Scope;
|
|
147
|
-
openElems: OpenElem[];
|
|
148
185
|
}
|
|
149
186
|
/** Human-readable error when parsing WESL fails. */
|
|
150
187
|
declare class WeslParseError extends Error {
|
|
@@ -254,26 +291,38 @@ declare function childIdent(child: Scope | Ident): child is Ident;
|
|
|
254
291
|
//#endregion
|
|
255
292
|
//#region src/AbstractElems.d.ts
|
|
256
293
|
/**
|
|
257
|
-
* AST structures describing
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* Uninteresting parts are 'TextElem' nodes, copied to output WGSL.
|
|
294
|
+
* AST structures describing WESL source. Each element holds its interesting
|
|
295
|
+
* parts as typed child fields (name, type, init, body, ...); emit walks those
|
|
296
|
+
* fields and reconstructs the surrounding WGSL syntax rather than copying spans.
|
|
261
297
|
*/
|
|
262
|
-
type AbstractElem = GrammarElem | SyntheticElem | ExpressionElem;
|
|
263
|
-
type GrammarElem =
|
|
264
|
-
type ContainerElem = AttributeElem | AliasElem | ConstAssertElem | ConstElem | ContinuingElem | UnknownExpressionElem | SimpleMemberRef | FnElem | TypedDeclElem | GlobalVarElem | LetElem | ModuleElem | OverrideElem | FnParamElem | StructElem | StructMemberElem | StuffElem | TypeRefElem | VarElem | StatementElem | SwitchClauseElem;
|
|
298
|
+
type AbstractElem = GrammarElem | SyntheticElem | ExpressionElem | UnknownExpressionElem;
|
|
299
|
+
type GrammarElem = ModuleElem | AttributeElem | Statement | SwitchClauseElem | AliasElem | GlobalVarElem | OverrideElem | StructElem | StructMemberElem | FnElem | FnParamElem | TypedDeclElem | TerminalElem | DoBlockElem;
|
|
265
300
|
/** Map from element kind string to element type, for type-safe element construction. */
|
|
266
301
|
type ElemKindMap = {
|
|
267
302
|
alias: AliasElem;
|
|
268
303
|
assert: ConstAssertElem;
|
|
304
|
+
block: BlockElem;
|
|
269
305
|
const: ConstElem;
|
|
270
306
|
continuing: ContinuingElem;
|
|
307
|
+
if: IfElem;
|
|
308
|
+
for: ForElem;
|
|
309
|
+
while: WhileElem;
|
|
310
|
+
loop: LoopElem;
|
|
311
|
+
switch: SwitchElem;
|
|
312
|
+
return: ReturnElem;
|
|
313
|
+
break: BreakElem;
|
|
314
|
+
continue: ContinueElem;
|
|
315
|
+
discard: DiscardElem;
|
|
316
|
+
assign: AssignElem;
|
|
317
|
+
increment: IncrementElem;
|
|
318
|
+
decrement: DecrementElem;
|
|
319
|
+
call: CallElem;
|
|
320
|
+
empty: EmptyElem;
|
|
271
321
|
gvar: GlobalVarElem;
|
|
272
322
|
let: LetElem;
|
|
273
323
|
member: StructMemberElem;
|
|
274
324
|
override: OverrideElem;
|
|
275
325
|
param: FnParamElem;
|
|
276
|
-
statement: StatementElem;
|
|
277
326
|
struct: StructElem;
|
|
278
327
|
"switch-clause": SwitchClauseElem;
|
|
279
328
|
type: TypeRefElem;
|
|
@@ -281,26 +330,36 @@ type ElemKindMap = {
|
|
|
281
330
|
};
|
|
282
331
|
/** Inspired by https://github.com/webgpu-tools/wesl-rs/blob/3b2434eac1b2ebda9eb8bfb25f43d8600d819872/crates/wgsl-parse/src/syntax.rs#L364 */
|
|
283
332
|
type ExpressionElem = Literal | RefIdentElem | TypeRefElem | ParenthesizedExpression | ComponentExpression | ComponentMemberExpression | UnaryExpression | BinaryExpression | FunctionCallExpression;
|
|
284
|
-
type TerminalElem = DirectiveElem | DeclIdentElem | NameElem | RefIdentElem |
|
|
285
|
-
type GlobalDeclarationElem = AliasElem | ConstElem | FnElem | GlobalVarElem | OverrideElem | StructElem;
|
|
333
|
+
type TerminalElem = DirectiveElem | DeclIdentElem | NameElem | RefIdentElem | ImportElem;
|
|
334
|
+
type GlobalDeclarationElem = AliasElem | ConstElem | DoBlockElem | FnElem | GlobalVarElem | OverrideElem | StructElem;
|
|
286
335
|
type DeclarationElem = GlobalDeclarationElem | FnParamElem | VarElem | LetElem;
|
|
287
336
|
type ElemWithAttributes = Extract<AbstractElem, HasAttributes>;
|
|
288
337
|
interface AbstractElemBase {
|
|
289
338
|
kind: AbstractElem["kind"];
|
|
290
339
|
start: number;
|
|
291
340
|
end: number;
|
|
341
|
+
/** Comments leading this element (on their own line above it). */
|
|
342
|
+
commentsBefore?: CommentElem[];
|
|
343
|
+
/** Comments trailing this element (on the same line after it). */
|
|
344
|
+
commentsAfter?: CommentElem[];
|
|
292
345
|
}
|
|
293
|
-
|
|
294
|
-
|
|
346
|
+
/**
|
|
347
|
+
* A source comment attached to an element as leading or trailing trivia.
|
|
348
|
+
* Not part of the {@link AbstractElem} union: comments are node metadata
|
|
349
|
+
* (in `commentsBefore` / `commentsAfter`), never `contents` children.
|
|
350
|
+
*/
|
|
351
|
+
interface CommentElem {
|
|
352
|
+
kind: "comment";
|
|
353
|
+
style: "line" | "block";
|
|
354
|
+
start: number;
|
|
355
|
+
end: number;
|
|
356
|
+
srcModule: SrcModule;
|
|
357
|
+
/** Preserve one blank line above this comment (leading comments only). */
|
|
358
|
+
blankBefore?: boolean;
|
|
295
359
|
}
|
|
296
360
|
interface HasAttributes {
|
|
297
361
|
attributes?: AttributeElem[];
|
|
298
362
|
}
|
|
299
|
-
/** Raw text copied to linked WGSL (e.g., 'var' or '@diagnostic(off,derivative_uniformity)'). */
|
|
300
|
-
interface TextElem extends AbstractElemBase {
|
|
301
|
-
kind: "text";
|
|
302
|
-
srcModule: SrcModule;
|
|
303
|
-
}
|
|
304
363
|
/** A name that doesn't need to be an Ident (e.g., struct member, diagnostic rule). */
|
|
305
364
|
interface NameElem extends AbstractElemBase {
|
|
306
365
|
kind: "name";
|
|
@@ -351,20 +410,20 @@ interface SyntheticElem {
|
|
|
351
410
|
text: string;
|
|
352
411
|
}
|
|
353
412
|
/** A declaration identifier with an optional type. */
|
|
354
|
-
interface TypedDeclElem extends
|
|
413
|
+
interface TypedDeclElem extends AbstractElemBase {
|
|
355
414
|
kind: "typeDecl";
|
|
356
415
|
decl: DeclIdentElem;
|
|
357
416
|
typeRef?: TypeRefElem;
|
|
358
417
|
typeScope?: Scope;
|
|
359
418
|
}
|
|
360
419
|
/** An alias statement. */
|
|
361
|
-
interface AliasElem extends
|
|
420
|
+
interface AliasElem extends AbstractElemBase, HasAttributes {
|
|
362
421
|
kind: "alias";
|
|
363
422
|
name: DeclIdentElem;
|
|
364
423
|
typeRef: TypeRefElem;
|
|
365
424
|
}
|
|
366
425
|
/** An attribute like '@compute' or '@binding(0)'. */
|
|
367
|
-
interface AttributeElem extends
|
|
426
|
+
interface AttributeElem extends AbstractElemBase {
|
|
368
427
|
kind: "attribute";
|
|
369
428
|
attribute: Attribute;
|
|
370
429
|
}
|
|
@@ -401,23 +460,27 @@ interface ElseAttribute {
|
|
|
401
460
|
}
|
|
402
461
|
type ConditionalAttribute = IfAttribute | ElifAttribute | ElseAttribute;
|
|
403
462
|
/** A const_assert statement. */
|
|
404
|
-
interface ConstAssertElem extends
|
|
463
|
+
interface ConstAssertElem extends AbstractElemBase, HasAttributes {
|
|
405
464
|
kind: "assert";
|
|
465
|
+
expression: ExpressionElem;
|
|
406
466
|
}
|
|
407
467
|
/** A const declaration. */
|
|
408
|
-
interface ConstElem extends
|
|
468
|
+
interface ConstElem extends AbstractElemBase, HasAttributes {
|
|
409
469
|
kind: "const";
|
|
410
470
|
name: TypedDeclElem;
|
|
471
|
+
init?: ExpressionElem;
|
|
411
472
|
}
|
|
412
473
|
/** An expression without special handling, used in attribute parameters. */
|
|
413
|
-
interface UnknownExpressionElem extends
|
|
474
|
+
interface UnknownExpressionElem extends AbstractElemBase {
|
|
414
475
|
kind: "expression";
|
|
476
|
+
expression: ExpressionElem;
|
|
415
477
|
}
|
|
416
478
|
/** An expression that can be safely evaluated at compile time. */
|
|
417
479
|
interface TranslateTimeExpressionElem {
|
|
418
480
|
kind: "translate-time-expression";
|
|
419
481
|
expression: ExpressionElem;
|
|
420
|
-
|
|
482
|
+
start: number;
|
|
483
|
+
end: number;
|
|
421
484
|
}
|
|
422
485
|
/** A literal value (boolean or number) in WESL source. */
|
|
423
486
|
interface Literal extends AbstractElemBase {
|
|
@@ -458,13 +521,21 @@ interface BinaryExpression extends AbstractElemBase {
|
|
|
458
521
|
interface FunctionCallExpression extends AbstractElemBase {
|
|
459
522
|
kind: "call-expression";
|
|
460
523
|
function: RefIdentElem | TypeRefElem;
|
|
524
|
+
/** Only populated for function calls; constructor calls carry templates on `function`. */
|
|
461
525
|
templateArgs?: TypeTemplateParameter[];
|
|
462
526
|
arguments: ExpressionElem[];
|
|
463
527
|
}
|
|
464
528
|
interface UnaryOperator {
|
|
465
529
|
value: "!" | "&" | "*" | "-" | "~";
|
|
466
|
-
|
|
530
|
+
start: number;
|
|
531
|
+
end: number;
|
|
467
532
|
}
|
|
533
|
+
/** Uses span (not inline start/end) so each operator object stays in a smaller
|
|
534
|
+
* V8 size class. Inline start/end uses slightly less memory overall (no separate
|
|
535
|
+
* span tuple) but each object is bigger and more likely to be promoted to old
|
|
536
|
+
* gen under sustained allocation pressure, triggering more major GCs and
|
|
537
|
+
* ~5% slower wall time on math-heavy parse workloads (bevy_env_map/parse).
|
|
538
|
+
* A rare case where allocating more bytes wins on GC. */
|
|
468
539
|
interface BinaryOperator {
|
|
469
540
|
value: ("||" | "&&" | "+" | "-" | "*" | "/" | "%" | "==") | ("!=" | "<" | "<=" | ">" | ">=" | "|" | "&" | "^") | ("<<" | ">>");
|
|
470
541
|
span: Span;
|
|
@@ -487,90 +558,198 @@ interface RequiresDirective {
|
|
|
487
558
|
kind: "requires";
|
|
488
559
|
extensions: NameElem[];
|
|
489
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* A `do` block: a CPU-side dispatch script (`do name(params) { ... }`).
|
|
563
|
+
*
|
|
564
|
+
* Module-local: its name and body idents never enter bindIdents/the scope
|
|
565
|
+
* tree, and the linker drops it entirely from emitted WGSL. The parsed body
|
|
566
|
+
* is retained for the interpreter, which resolves names by AST match.
|
|
567
|
+
*/
|
|
568
|
+
interface DoBlockElem extends AbstractElemBase, HasAttributes {
|
|
569
|
+
kind: "do";
|
|
570
|
+
name: NameElem;
|
|
571
|
+
params: FnParamElem[];
|
|
572
|
+
body: BlockElem;
|
|
573
|
+
}
|
|
490
574
|
/** A function declaration. */
|
|
491
|
-
interface FnElem extends
|
|
575
|
+
interface FnElem extends AbstractElemBase, HasAttributes {
|
|
492
576
|
kind: "fn";
|
|
493
577
|
name: DeclIdentElem;
|
|
494
578
|
params: FnParamElem[];
|
|
495
|
-
body:
|
|
579
|
+
body: BlockElem;
|
|
496
580
|
returnAttributes?: AttributeElem[];
|
|
497
581
|
returnType?: TypeRefElem;
|
|
498
582
|
}
|
|
499
583
|
/** A global variable declaration (at the root level). */
|
|
500
|
-
interface GlobalVarElem extends
|
|
584
|
+
interface GlobalVarElem extends AbstractElemBase, HasAttributes {
|
|
501
585
|
kind: "gvar";
|
|
502
586
|
name: TypedDeclElem;
|
|
587
|
+
/** Address-space / access-mode enumerants, e.g. `<storage, read_write>`. */
|
|
588
|
+
template?: NameElem[];
|
|
589
|
+
init?: ExpressionElem;
|
|
503
590
|
}
|
|
504
591
|
/** An entire file. */
|
|
505
|
-
interface ModuleElem extends
|
|
592
|
+
interface ModuleElem extends AbstractElemBase {
|
|
506
593
|
kind: "module";
|
|
594
|
+
/** Top-level children (imports, directives, declarations, and any synthetic
|
|
595
|
+
* vars added by transforms) in source order. */
|
|
596
|
+
decls: AbstractElem[];
|
|
507
597
|
}
|
|
508
598
|
/** An override declaration. */
|
|
509
|
-
interface OverrideElem extends
|
|
599
|
+
interface OverrideElem extends AbstractElemBase, HasAttributes {
|
|
510
600
|
kind: "override";
|
|
511
601
|
name: TypedDeclElem;
|
|
602
|
+
init?: ExpressionElem;
|
|
512
603
|
}
|
|
513
604
|
/** A parameter in a function declaration. */
|
|
514
|
-
interface FnParamElem extends
|
|
605
|
+
interface FnParamElem extends AbstractElemBase, HasAttributes {
|
|
515
606
|
kind: "param";
|
|
516
607
|
name: TypedDeclElem;
|
|
517
608
|
}
|
|
518
|
-
/** Simple struct references like `myStruct.bar` (for binding struct transforms). */
|
|
519
|
-
interface SimpleMemberRef extends ElemWithContentsBase {
|
|
520
|
-
kind: "memberRef";
|
|
521
|
-
name: RefIdentElem;
|
|
522
|
-
member: NameElem;
|
|
523
|
-
extraComponents?: StuffElem;
|
|
524
|
-
}
|
|
525
609
|
/** A struct declaration. */
|
|
526
|
-
interface StructElem extends
|
|
610
|
+
interface StructElem extends AbstractElemBase, HasAttributes {
|
|
527
611
|
kind: "struct";
|
|
528
612
|
name: DeclIdentElem;
|
|
529
613
|
members: StructMemberElem[];
|
|
530
|
-
bindingStruct?: true;
|
|
531
|
-
}
|
|
532
|
-
/** Generic container of other elements. */
|
|
533
|
-
interface StuffElem extends ElemWithContentsBase {
|
|
534
|
-
kind: "stuff";
|
|
535
|
-
}
|
|
536
|
-
/** A struct declaration marked as a binding struct. */
|
|
537
|
-
interface BindingStructElem extends StructElem {
|
|
538
|
-
bindingStruct: true;
|
|
539
|
-
entryFn?: FnElem;
|
|
540
614
|
}
|
|
541
615
|
/** A member of a struct declaration. */
|
|
542
|
-
interface StructMemberElem extends
|
|
616
|
+
interface StructMemberElem extends AbstractElemBase, HasAttributes {
|
|
543
617
|
kind: "member";
|
|
544
618
|
name: NameElem;
|
|
545
619
|
typeRef: TypeRefElem;
|
|
546
|
-
mangledVarName?: string;
|
|
547
620
|
}
|
|
548
621
|
type TypeTemplateParameter = ExpressionElem;
|
|
549
622
|
/** A type reference like 'f32', 'MyStruct', or 'ptr<storage, array<f32>, read_only>'. */
|
|
550
|
-
interface TypeRefElem extends
|
|
623
|
+
interface TypeRefElem extends AbstractElemBase {
|
|
551
624
|
kind: "type";
|
|
552
625
|
name: RefIdent;
|
|
553
626
|
templateParams?: TypeTemplateParameter[];
|
|
554
627
|
}
|
|
555
628
|
/** A variable declaration. */
|
|
556
|
-
interface VarElem extends
|
|
629
|
+
interface VarElem extends AbstractElemBase, HasAttributes {
|
|
557
630
|
kind: "var";
|
|
558
631
|
name: TypedDeclElem;
|
|
632
|
+
/** Address-space / access-mode enumerants, e.g. `<storage, read_write>`. */
|
|
633
|
+
template?: NameElem[];
|
|
634
|
+
init?: ExpressionElem;
|
|
559
635
|
}
|
|
560
|
-
interface LetElem extends
|
|
636
|
+
interface LetElem extends AbstractElemBase, HasAttributes {
|
|
561
637
|
kind: "let";
|
|
562
638
|
name: TypedDeclElem;
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
639
|
+
init?: ExpressionElem;
|
|
640
|
+
}
|
|
641
|
+
/** Any WGSL statement inside a function or block body. */
|
|
642
|
+
type Statement = BlockElem | IfElem | ForElem | WhileElem | LoopElem | ContinuingElem | SwitchElem | ReturnElem | BreakElem | ContinueElem | DiscardElem | AssignElem | IncrementElem | DecrementElem | CallElem | ConstAssertElem | EmptyElem | VarElem | LetElem | ConstElem;
|
|
643
|
+
/** A bare `;` statement. Emits nothing, but kept in the AST as a statement node. */
|
|
644
|
+
interface EmptyElem extends AbstractElemBase, HasAttributes {
|
|
645
|
+
kind: "empty";
|
|
646
|
+
}
|
|
647
|
+
/** A `{ ... }` compound statement. */
|
|
648
|
+
interface BlockElem extends AbstractElemBase, HasAttributes {
|
|
649
|
+
kind: "block";
|
|
650
|
+
body: Statement[];
|
|
651
|
+
/** Comments inside an otherwise empty block, with no statement to attach to. */
|
|
652
|
+
innerComments?: CommentElem[];
|
|
653
|
+
}
|
|
654
|
+
/** An if / else-if / else chain. `else` nests: else-if is an IfElem, plain else a BlockElem. */
|
|
655
|
+
interface IfElem extends AbstractElemBase, HasAttributes {
|
|
656
|
+
kind: "if";
|
|
657
|
+
condition: ExpressionElem;
|
|
658
|
+
body: BlockElem;
|
|
659
|
+
else?: IfElem | BlockElem;
|
|
660
|
+
}
|
|
661
|
+
/** A for loop. */
|
|
662
|
+
interface ForElem extends AbstractElemBase, HasAttributes {
|
|
663
|
+
kind: "for";
|
|
664
|
+
init?: ForInit;
|
|
665
|
+
condition?: ExpressionElem;
|
|
666
|
+
update?: ForUpdate;
|
|
667
|
+
body: BlockElem;
|
|
668
|
+
}
|
|
669
|
+
type ForInit = VarElem | LetElem | ConstElem | AssignElem | IncrementElem | DecrementElem | CallElem;
|
|
670
|
+
type ForUpdate = AssignElem | IncrementElem | DecrementElem | CallElem;
|
|
671
|
+
/** A while loop. */
|
|
672
|
+
interface WhileElem extends AbstractElemBase, HasAttributes {
|
|
673
|
+
kind: "while";
|
|
674
|
+
condition: ExpressionElem;
|
|
675
|
+
body: BlockElem;
|
|
676
|
+
}
|
|
677
|
+
/** A loop, optionally ending with a continuing block. */
|
|
678
|
+
interface LoopElem extends AbstractElemBase, HasAttributes {
|
|
679
|
+
kind: "loop";
|
|
680
|
+
body: BlockElem;
|
|
681
|
+
continuing?: ContinuingElem;
|
|
682
|
+
}
|
|
683
|
+
/** A continuing block, optionally ending with `break if expr`. */
|
|
684
|
+
interface ContinuingElem extends AbstractElemBase, HasAttributes {
|
|
568
685
|
kind: "continuing";
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
686
|
+
body: BlockElem;
|
|
687
|
+
breakIf?: ExpressionElem;
|
|
688
|
+
}
|
|
689
|
+
/** A switch statement. */
|
|
690
|
+
interface SwitchElem extends AbstractElemBase, HasAttributes {
|
|
691
|
+
kind: "switch";
|
|
692
|
+
selector: ExpressionElem;
|
|
693
|
+
clauses: SwitchClauseElem[];
|
|
694
|
+
/** Attributes on the switch body, between the selector and `{`. */
|
|
695
|
+
bodyAttributes?: AttributeElem[];
|
|
696
|
+
}
|
|
697
|
+
/** A case or default clause. `"default"` sentinel marks the default selector. */
|
|
698
|
+
interface SwitchClauseElem extends AbstractElemBase, HasAttributes {
|
|
573
699
|
kind: "switch-clause";
|
|
700
|
+
selectors: (ExpressionElem | "default")[];
|
|
701
|
+
body: BlockElem;
|
|
702
|
+
}
|
|
703
|
+
/** A return statement, with an optional value. */
|
|
704
|
+
interface ReturnElem extends AbstractElemBase, HasAttributes {
|
|
705
|
+
kind: "return";
|
|
706
|
+
value?: ExpressionElem;
|
|
707
|
+
}
|
|
708
|
+
/** A break statement, or `break if expr`. */
|
|
709
|
+
interface BreakElem extends AbstractElemBase, HasAttributes {
|
|
710
|
+
kind: "break";
|
|
711
|
+
condition?: ExpressionElem;
|
|
712
|
+
}
|
|
713
|
+
/** A continue statement. */
|
|
714
|
+
interface ContinueElem extends AbstractElemBase, HasAttributes {
|
|
715
|
+
kind: "continue";
|
|
716
|
+
}
|
|
717
|
+
/** A discard statement. */
|
|
718
|
+
interface DiscardElem extends AbstractElemBase, HasAttributes {
|
|
719
|
+
kind: "discard";
|
|
720
|
+
}
|
|
721
|
+
/** Assignment, compound assignment, or phony `_ = expr`. */
|
|
722
|
+
interface AssignElem extends AbstractElemBase, HasAttributes {
|
|
723
|
+
kind: "assign";
|
|
724
|
+
lhs: ExpressionElem | PhonyTarget;
|
|
725
|
+
op: AssignOp;
|
|
726
|
+
rhs: ExpressionElem;
|
|
727
|
+
}
|
|
728
|
+
/** `i++` */
|
|
729
|
+
interface IncrementElem extends AbstractElemBase, HasAttributes {
|
|
730
|
+
kind: "increment";
|
|
731
|
+
target: ExpressionElem;
|
|
732
|
+
}
|
|
733
|
+
/** `i--` */
|
|
734
|
+
interface DecrementElem extends AbstractElemBase, HasAttributes {
|
|
735
|
+
kind: "decrement";
|
|
736
|
+
target: ExpressionElem;
|
|
737
|
+
}
|
|
738
|
+
/** A bare function call statement. */
|
|
739
|
+
interface CallElem extends AbstractElemBase, HasAttributes {
|
|
740
|
+
kind: "call";
|
|
741
|
+
call: FunctionCallExpression;
|
|
742
|
+
}
|
|
743
|
+
/** The `_` discard target of a phony assignment; never enters the ident system. */
|
|
744
|
+
interface PhonyTarget {
|
|
745
|
+
kind: "phony";
|
|
746
|
+
span: Span;
|
|
747
|
+
}
|
|
748
|
+
/** An assignment operator. Uses a span tuple (not inline start/end) to match
|
|
749
|
+
* BinaryOperator's smaller V8 size class; see the note there. */
|
|
750
|
+
interface AssignOp {
|
|
751
|
+
value: ("=" | "+=" | "-=" | "*=" | "/=" | "%=") | ("&=" | "|=" | "^=" | "<<=" | ">>=");
|
|
752
|
+
span: Span;
|
|
574
753
|
}
|
|
575
754
|
//#endregion
|
|
576
755
|
//#region src/SrcMap.d.ts
|
|
@@ -628,8 +807,6 @@ declare class SrcMapBuilder {
|
|
|
628
807
|
addSynthetic(fragment: string, syntheticSource: string, srcStart: number, srcEnd: number): void;
|
|
629
808
|
/** append a synthetic newline, mapped to previous source location */
|
|
630
809
|
addNl(): void;
|
|
631
|
-
/** copy a string fragment from the src to the destination string */
|
|
632
|
-
addCopy(srcStart: number, srcEnd: number): void;
|
|
633
810
|
/** return a SrcMap */
|
|
634
811
|
static build(builders: SrcMapBuilder[]): SrcMap;
|
|
635
812
|
}
|
|
@@ -787,6 +964,8 @@ interface RecordResolverOptions {
|
|
|
787
964
|
packageName?: string;
|
|
788
965
|
/** Debug path prefix for error messages */
|
|
789
966
|
debugWeslRoot?: string;
|
|
967
|
+
/** Enable experimental, not-yet-spec'd syntax extensions while parsing. */
|
|
968
|
+
weslExtensions?: WeslExtensions;
|
|
790
969
|
}
|
|
791
970
|
/** Module resolver for in-memory source records. Lazy by default. */
|
|
792
971
|
declare class RecordResolver implements BatchModuleResolver {
|
|
@@ -794,6 +973,7 @@ declare class RecordResolver implements BatchModuleResolver {
|
|
|
794
973
|
readonly sources: Record<string, string>;
|
|
795
974
|
readonly packageName: string;
|
|
796
975
|
readonly debugWeslRoot: string;
|
|
976
|
+
readonly weslExtensions?: WeslExtensions;
|
|
797
977
|
constructor(sources: Record<string, string>, options?: RecordResolverOptions);
|
|
798
978
|
resolveModule(modulePath: string): WeslAST | undefined;
|
|
799
979
|
private findSource;
|
|
@@ -874,9 +1054,13 @@ interface LinkParams {
|
|
|
874
1054
|
constants?: Record<string, string | number>;
|
|
875
1055
|
/** function to construct globally unique wgsl identifiers */
|
|
876
1056
|
mangler?: ManglerFn;
|
|
1057
|
+
/** opt-in parsing of experimental, not-yet-spec'd syntax extensions.
|
|
1058
|
+
* Only applied to the local source resolver built from `weslSrc`; callers
|
|
1059
|
+
* that supply their own `resolver` must set it on that resolver. */
|
|
1060
|
+
weslExtensions?: WeslExtensions;
|
|
877
1061
|
}
|
|
878
1062
|
/** Project config for web components and tools. */
|
|
879
|
-
type WeslProject = Pick<LinkParams, "weslSrc" | "rootModuleName" | "conditions" | "constants" | "libs" | "packageName"> & {
|
|
1063
|
+
type WeslProject = Pick<LinkParams, "weslSrc" | "rootModuleName" | "conditions" | "constants" | "libs" | "packageName" | "weslExtensions"> & {
|
|
880
1064
|
/** Shader directory relative to project root (set by ?link from wesl.toml). */shaderRoot?: string;
|
|
881
1065
|
};
|
|
882
1066
|
/** Context passed to virtual library generators. */
|
|
@@ -1026,7 +1210,6 @@ declare function filterValidElements<T extends AbstractElem>(elements: readonly
|
|
|
1026
1210
|
declare function astToString(elem: AbstractElem, indent?: number): string;
|
|
1027
1211
|
/** @return string representation of an attribute (for test/debug) */
|
|
1028
1212
|
declare function attributeToString(attr: Attribute): string;
|
|
1029
|
-
declare function debugContentsToString(elem: StuffElem): string;
|
|
1030
1213
|
//#endregion
|
|
1031
1214
|
//#region src/debug/ScopeToString.d.ts
|
|
1032
1215
|
/** A debugging print of the scope tree with identifiers in nested brackets */
|
|
@@ -1110,6 +1293,20 @@ declare function sanitizePackageName(npmName: string): string;
|
|
|
1110
1293
|
*/
|
|
1111
1294
|
declare function npmNameVariations(sanitizedPath: string): Generator<string>;
|
|
1112
1295
|
//#endregion
|
|
1296
|
+
//#region src/LinkerUtil.d.ts
|
|
1297
|
+
/** A module's top-level declarations of a given kind, narrowed to that elem type. */
|
|
1298
|
+
declare function declsOfKind<K extends AbstractElem["kind"]>(moduleElem: ModuleElem, kind: K): Extract<AbstractElem, {
|
|
1299
|
+
kind: K;
|
|
1300
|
+
}>[];
|
|
1301
|
+
/** Visit an elem and all its descendants, parent before children (pre-order). */
|
|
1302
|
+
declare function visitAst(elem: AbstractElem, visitor: (elem: AbstractElem) => void): void;
|
|
1303
|
+
/**
|
|
1304
|
+
* Child elems of any AST node: the typed structural fields (attributes plus
|
|
1305
|
+
* body / condition / decls / ...) in source order. Returns [] for leaf elems.
|
|
1306
|
+
*/
|
|
1307
|
+
declare function childElems(elem: AbstractElem): readonly AbstractElem[];
|
|
1308
|
+
declare function identElemLog(identElem: DeclIdentElem | RefIdentElem, ...messages: any[]): void;
|
|
1309
|
+
//#endregion
|
|
1113
1310
|
//#region src/Logging.d.ts
|
|
1114
1311
|
/** base logger (can be overridden to a capturing logger for tests) */
|
|
1115
1312
|
declare let log: (...data: any[]) => void;
|
|
@@ -1172,57 +1369,6 @@ declare function stdFn(name: string): boolean;
|
|
|
1172
1369
|
/** return true if the name is for a built in enumerant */
|
|
1173
1370
|
declare function stdEnumerant(name: string): boolean;
|
|
1174
1371
|
//#endregion
|
|
1175
|
-
//#region src/TransformBindingStructs.d.ts
|
|
1176
|
-
declare function bindingStructsPlugin(): WeslJsPlugin;
|
|
1177
|
-
/**
|
|
1178
|
-
* Transform binding structures into binding variables by mutating the AST.
|
|
1179
|
-
*
|
|
1180
|
-
* First we find all the binding structs:
|
|
1181
|
-
* . find all the structs in the module by filtering the moduleElem.contents
|
|
1182
|
-
* . for each struct:
|
|
1183
|
-
* . mark any structs with that contain @group or @binding annotations as 'binding structs' and save them in a list
|
|
1184
|
-
* . (later) create reverse links from structs to struct members
|
|
1185
|
-
* . (later) visit all the binding structs and traverse to referencing structs, marking the referencing structs as binding structs too
|
|
1186
|
-
* Generate synethic AST nodes for binding variables
|
|
1187
|
-
*
|
|
1188
|
-
* Find all references to binding struct members
|
|
1189
|
-
* . find the componound idents by traversing moduleElem.contents
|
|
1190
|
-
* . filter to find the compound idents that refer to 'binding structs'
|
|
1191
|
-
* . go from each ident to its declaration,
|
|
1192
|
-
* . declaration to typeRef reference
|
|
1193
|
-
* . typeRef to type declaration
|
|
1194
|
-
* . check type declaration to see if it's a binding struct
|
|
1195
|
-
* . record the intermediate declaration (e.g. a fn param b:Bindings from 'fn(b:Bindings)' )
|
|
1196
|
-
* rewrite references to binding struct members as synthetic elements
|
|
1197
|
-
*
|
|
1198
|
-
* Remove the binding structs from the AST
|
|
1199
|
-
* Remove the intermediate fn param declarations from the AST
|
|
1200
|
-
* Add the new binding variables to the AST
|
|
1201
|
-
*
|
|
1202
|
-
* @return the binding structs and the mutated AST
|
|
1203
|
-
*/
|
|
1204
|
-
declare function lowerBindingStructs(ast: TransformedAST): TransformedAST;
|
|
1205
|
-
declare function markEntryTypes(moduleElem: ModuleElem, bindingStructs: BindingStructElem[]): void;
|
|
1206
|
-
/** mutate the AST, marking StructElems as bindingStructs
|
|
1207
|
-
* (if they contain ptrs with @group @binding annotations)
|
|
1208
|
-
* @return the binding structs
|
|
1209
|
-
*/
|
|
1210
|
-
declare function markBindingStructs(moduleElem: ModuleElem): BindingStructElem[];
|
|
1211
|
-
/** convert each member of the binding struct into a synthetic global variable */
|
|
1212
|
-
declare function transformBindingStruct(s: StructElem, globalNames: Set<string>): SyntheticElem[];
|
|
1213
|
-
interface MemberRefToStruct extends StructTrace {
|
|
1214
|
-
memberRef: SimpleMemberRef;
|
|
1215
|
-
}
|
|
1216
|
-
interface StructTrace {
|
|
1217
|
-
struct: StructElem;
|
|
1218
|
-
intermediates: DeclarationElem[];
|
|
1219
|
-
}
|
|
1220
|
-
/** find all simple member references in the module that refer to binding structs */
|
|
1221
|
-
declare function findRefsToBindingStructs(moduleElem: ModuleElem): MemberRefToStruct[];
|
|
1222
|
-
/** Mutate the member reference elem to instead contain synthetic elem text.
|
|
1223
|
-
* The new text is the mangled var name of the struct member that the memberRef refers to. */
|
|
1224
|
-
declare function transformBindingReference(memberRef: SimpleMemberRef, struct: StructElem): SyntheticElem;
|
|
1225
|
-
//#endregion
|
|
1226
1372
|
//#region src/Util.d.ts
|
|
1227
1373
|
declare function multiKeySet<A, B, V>(m: Map<A, Map<B, V>>, a: A, b: B, v: V): void;
|
|
1228
1374
|
/** replace strings in a text according to a relacement map
|
|
@@ -1267,4 +1413,4 @@ declare function offsetToLineNumber(offset: number, text: string): [lineNum: num
|
|
|
1267
1413
|
*/
|
|
1268
1414
|
declare function errorHighlight(source: string, span: Span): [string, string];
|
|
1269
1415
|
//#endregion
|
|
1270
|
-
export { AbstractElem, AbstractElemBase, AliasElem, Attribute, AttributeElem, BatchModuleResolver, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST,
|
|
1416
|
+
export { AbstractElem, AbstractElemBase, AliasElem, AssignElem, AssignOp, Attribute, AttributeElem, BatchModuleResolver, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST, BlockElem, BoundAndTransformed, BreakElem, BuiltinAttribute, BundleResolver, CallElem, CommentElem, ComponentExpression, ComponentMemberExpression, CompositeResolver, ConditionalAttribute, Conditions, ConstAssertElem, ConstElem, ContinueElem, ContinuingElem, DeclIdent, DeclIdentElem, DeclarationElem, DecrementElem, DiagnosticAttribute, DiagnosticDirective, DiagnosticRule, DirectiveElem, DirectiveVariant, DiscardElem, DoBlockElem, ElemKindMap, ElemWithAttributes, ElifAttribute, ElseAttribute, EmittableElem, EmptyElem, EnableDirective, ExpressionElem, ExtendedGPUValidationError, FnElem, FnParamElem, ForElem, ForInit, ForUpdate, FunctionCallExpression, GlobalDeclarationElem, GlobalVarElem, GrammarElem, HasAttributes, Ident, IfAttribute, IfElem, ImportCollection, ImportElem, ImportItem, ImportSegment, ImportStatement, IncrementElem, InterpolateAttribute, LetElem, LexicalScope, LinkConfig, LinkParams, LinkRegistryParams, LinkedWesl, LinkerTransform, Literal, LiveDecls, LoopElem, ManglerFn, ModuleElem, ModuleResolver, NameElem, OverrideElem, ParenthesizedExpression, ParseError, type ParseOptions, PartialScope, PhonyTarget, RecordResolver, RecordResolverOptions, RefIdent, RefIdentElem, RequiresDirective, ReturnElem, Scope, ScopeItem, Span, SrcMap, SrcMapBuilder, SrcMapEntry, SrcModule, SrcPosition, SrcWithPath, StableState, StandardAttribute, Statement, StructElem, StructMemberElem, SwitchClauseElem, SwitchElem, SyntheticElem, TerminalElem, TrackingResolver, TransformedAST, TranslateTimeExpressionElem, TypeRefElem, TypeTemplateParameter, TypedDeclElem, UnaryExpression, UnaryOperator, UnboundRef, UnknownExpressionElem, VarElem, VirtualLibContext, VirtualLibrary, VirtualLibraryFn, VirtualLibrarySet, WeslAST, WeslBundle, WeslDevice, type WeslExtensions, WeslGPUCompilationInfo, WeslGPUCompilationMessage, WeslJsPlugin, WeslParseContext, WeslParseError, WeslParseState, WeslProject, WeslStream, WhileElem, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, childElems, childIdent, childScope, containsScope, debug, declsOfKind, discoverModules, emptyScope, errorHighlight, fileToModulePath, filterMap, filterValidElements, findAllRootDecls, findMap, findUnboundIdents, findUnboundRefs, findValidRootDecls, flatImports, freshResolver, groupBy, grouped, identElemLog, identToString, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, log, makeLiveDecls, makeWeslDevice, mapForward, mapValues, mergeScope, minimalMangle, minimallyMangledName, modulePartsToRelativePath, moduleToRelativePath, multiKeySet, multisampledTextureTypes, nextIdentId, noSuffix, normalize, normalizeDebugRoot, normalizeModuleName, npmNameVariations, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, resolveModulePath, sampledTextureTypes, sanitizePackageName, scan, scopeToString, scopeToStringLong, srcLog, stdEnumerant, stdEnumerants, stdFn, stdFns, stdType, stdTypes, textureStorageTypes, underscoreMangle, validation, visitAst, wgslStandardAttributes, withLoggerAsync };
|