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.
Files changed (61) hide show
  1. package/dist/index.d.ts +272 -126
  2. package/dist/index.js +1742 -1102
  3. package/package.json +1 -1
  4. package/src/AbstractElems.ts +263 -81
  5. package/src/Linker.ts +14 -2
  6. package/src/LinkerUtil.ts +141 -7
  7. package/src/LowerAndEmit.ts +660 -304
  8. package/src/ModuleResolver.ts +15 -4
  9. package/src/ParseWESL.ts +21 -33
  10. package/src/SrcMap.ts +7 -19
  11. package/src/debug/ASTtoString.ts +92 -76
  12. package/src/index.ts +1 -1
  13. package/src/parse/AttachComments.ts +289 -0
  14. package/src/parse/ExpressionUtil.ts +3 -3
  15. package/src/parse/ParseAttribute.ts +49 -71
  16. package/src/parse/ParseCall.ts +3 -4
  17. package/src/parse/ParseControlFlow.ts +100 -56
  18. package/src/parse/ParseDirective.ts +9 -8
  19. package/src/parse/ParseDoBlock.ts +63 -0
  20. package/src/parse/ParseExpression.ts +11 -10
  21. package/src/parse/ParseFn.ts +11 -33
  22. package/src/parse/ParseGlobalVar.ts +36 -27
  23. package/src/parse/ParseIdent.ts +4 -5
  24. package/src/parse/ParseLocalVar.ts +16 -12
  25. package/src/parse/ParseLoop.ts +76 -39
  26. package/src/parse/ParseModule.ts +65 -19
  27. package/src/parse/ParseSimpleStatement.ts +112 -66
  28. package/src/parse/ParseStatement.ts +39 -66
  29. package/src/parse/ParseStruct.ts +8 -22
  30. package/src/parse/ParseType.ts +10 -13
  31. package/src/parse/ParseUtil.ts +26 -12
  32. package/src/parse/ParseValueDeclaration.ts +18 -31
  33. package/src/parse/ParseWesl.ts +11 -14
  34. package/src/parse/ParsingContext.ts +11 -9
  35. package/src/parse/WeslStream.ts +138 -121
  36. package/src/parse/stream/RegexMatchers.ts +45 -0
  37. package/src/parse/stream/WeslLexer.ts +249 -0
  38. package/src/test/BevyLink.test.ts +17 -10
  39. package/src/test/ConditionalElif.test.ts +4 -2
  40. package/src/test/DeclCommentEmit.test.ts +122 -0
  41. package/src/test/DoBlock.test.ts +164 -0
  42. package/src/test/FilterValidElements.test.ts +4 -6
  43. package/src/test/Linker.test.ts +23 -7
  44. package/src/test/Mangling.test.ts +8 -4
  45. package/src/test/ParseComments.test.ts +234 -6
  46. package/src/test/ParseConditionsV2.test.ts +47 -175
  47. package/src/test/ParseElifV2.test.ts +12 -33
  48. package/src/test/ParseErrorV2.test.ts +0 -0
  49. package/src/test/ParseWeslV2.test.ts +247 -626
  50. package/src/test/StatementEmit.test.ts +143 -0
  51. package/src/test/StripWesl.ts +24 -3
  52. package/src/test/TestLink.ts +19 -3
  53. package/src/test/TestUtil.ts +18 -8
  54. package/src/test/Tokenizer.test.ts +96 -0
  55. package/src/test/__snapshots__/ParseWeslV2.test.ts.snap +10 -42
  56. package/src/RawEmit.ts +0 -103
  57. package/src/Reflection.ts +0 -336
  58. package/src/TransformBindingStructs.ts +0 -320
  59. package/src/parse/ContentsHelpers.ts +0 -70
  60. package/src/parse/stream/CachingStream.ts +0 -48
  61. package/src/parse/stream/MatchersStream.ts +0 -85
package/src/LinkerUtil.ts CHANGED
@@ -1,22 +1,40 @@
1
1
  import type {
2
2
  AbstractElem,
3
- ContainerElem,
4
3
  DeclIdentElem,
4
+ ExpressionElem,
5
+ HasAttributes,
6
+ ModuleElem,
5
7
  RefIdentElem,
6
8
  } from "./AbstractElems.ts";
9
+ import { assertUnreachableSilent } from "./Assertions.ts";
7
10
  import { srcLog } from "./Logging.ts";
8
11
 
12
+ /** A module's top-level declarations of a given kind, narrowed to that elem type. */
13
+ export function declsOfKind<K extends AbstractElem["kind"]>(
14
+ moduleElem: ModuleElem,
15
+ kind: K,
16
+ ): Extract<AbstractElem, { kind: K }>[] {
17
+ return moduleElem.decls.filter(
18
+ (e): e is Extract<AbstractElem, { kind: K }> => e.kind === kind,
19
+ );
20
+ }
21
+
22
+ /** Visit an elem and all its descendants, parent before children (pre-order). */
9
23
  export function visitAst(
10
24
  elem: AbstractElem,
11
25
  visitor: (elem: AbstractElem) => void,
12
26
  ) {
13
27
  visitor(elem);
14
- if ((elem as ContainerElem).contents) {
15
- const container = elem as ContainerElem;
16
- container.contents.forEach(child => {
17
- visitAst(child, visitor);
18
- });
19
- }
28
+ for (const child of childElems(elem)) visitAst(child, visitor);
29
+ }
30
+
31
+ /**
32
+ * Child elems of any AST node: the typed structural fields (attributes plus
33
+ * body / condition / decls / ...) in source order. Returns [] for leaf elems.
34
+ */
35
+ export function childElems(elem: AbstractElem): readonly AbstractElem[] {
36
+ const attributes = (elem as HasAttributes).attributes ?? [];
37
+ return [...attributes, ...structuralFields(elem)];
20
38
  }
21
39
 
22
40
  export function identElemLog(
@@ -29,3 +47,119 @@ export function identElemLog(
29
47
  ...messages,
30
48
  );
31
49
  }
50
+
51
+ /** The child elems held in a node's typed fields, in source order (attributes
52
+ * are added separately by {@link childElems}). Empty for leaf kinds. The
53
+ * switch is exhaustive: a new elem kind without a case fails to compile in the
54
+ * default, so children can't be silently dropped. */
55
+ function structuralFields(elem: AbstractElem): AbstractElem[] {
56
+ switch (elem.kind) {
57
+ case "module":
58
+ return elem.decls;
59
+ case "var":
60
+ case "gvar":
61
+ return [
62
+ ...(elem.template ?? []),
63
+ elem.name,
64
+ ...(elem.init ? [elem.init] : []),
65
+ ];
66
+ case "let":
67
+ case "const":
68
+ case "override":
69
+ return [elem.name, ...(elem.init ? [elem.init] : [])];
70
+ case "alias":
71
+ return [elem.name, elem.typeRef];
72
+ case "assert":
73
+ return [elem.expression];
74
+ case "struct":
75
+ return [elem.name, ...elem.members];
76
+ case "member":
77
+ return [elem.name, elem.typeRef];
78
+ case "type":
79
+ return [elem.name.refIdentElem, ...(elem.templateParams ?? [])];
80
+ case "expression":
81
+ return [elem.expression];
82
+ case "binary-expression":
83
+ return [elem.left, elem.right];
84
+ case "unary-expression":
85
+ case "parenthesized-expression":
86
+ return [elem.expression];
87
+ case "component-expression":
88
+ return [elem.base, elem.access];
89
+ case "component-member-expression":
90
+ return [elem.base, elem.access];
91
+ case "call-expression":
92
+ return [elem.function, ...(elem.templateArgs ?? []), ...elem.arguments];
93
+ case "param":
94
+ return [elem.name];
95
+ case "typeDecl":
96
+ return elem.typeRef ? [elem.decl, elem.typeRef] : [elem.decl];
97
+ case "fn":
98
+ return [
99
+ elem.name,
100
+ ...elem.params,
101
+ ...(elem.returnType ? [elem.returnType] : []),
102
+ elem.body,
103
+ ];
104
+ case "block":
105
+ return elem.body;
106
+ case "if":
107
+ return [elem.condition, elem.body, ...(elem.else ? [elem.else] : [])];
108
+ case "for":
109
+ return [elem.init, elem.condition, elem.update, elem.body].filter(
110
+ isDefined,
111
+ );
112
+ case "while":
113
+ return [elem.condition, elem.body];
114
+ case "loop":
115
+ case "continuing":
116
+ return [elem.body];
117
+ case "switch":
118
+ return [elem.selector, ...(elem.bodyAttributes ?? []), ...elem.clauses];
119
+ case "switch-clause":
120
+ return [...exprSelectors(elem.selectors), elem.body];
121
+ case "return":
122
+ return elem.value ? [elem.value] : [];
123
+ case "break":
124
+ return elem.condition ? [elem.condition] : [];
125
+ case "assign":
126
+ return elem.lhs.kind === "phony" ? [elem.rhs] : [elem.lhs, elem.rhs];
127
+ case "increment":
128
+ case "decrement":
129
+ return [elem.target];
130
+ case "call":
131
+ return [elem.call];
132
+ case "continue":
133
+ case "discard":
134
+ case "empty":
135
+ return [];
136
+ case "do":
137
+ return [elem.name, ...elem.params, elem.body];
138
+ // import/directive hold no child elems in typed fields (their payload isn't
139
+ // an AbstractElem), but they carry attributes that childElems prepends.
140
+ case "import":
141
+ case "directive":
142
+ // leaf kinds: no child elems and no attributes.
143
+ case "attribute":
144
+ case "name":
145
+ case "literal":
146
+ case "ref":
147
+ case "decl":
148
+ case "synthetic":
149
+ return [];
150
+ default:
151
+ assertUnreachableSilent(elem);
152
+ return [];
153
+ }
154
+ }
155
+
156
+ function isDefined<T>(value: T | undefined): value is T {
157
+ return value !== undefined;
158
+ }
159
+
160
+ /** Drop the `"default"` sentinel, keeping only real case-selector expressions. */
161
+ function exprSelectors(
162
+ selectors: (ExpressionElem | "default")[],
163
+ ): ExpressionElem[] {
164
+ return selectors.filter((s): s is ExpressionElem => s !== "default");
165
+ }