@luma.gl/shadertools 9.0.14 → 9.0.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.
- package/dist/dist.dev.js +983 -248
- package/dist/dist.min.js +75 -75
- package/dist/index.cjs +15 -2832
- package/dist/index.cjs.map +4 -4
- package/dist/lib/shader-module/shader-module.d.ts +5 -3
- package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
- package/dist/lib/wgsl/get-shader-layout-wgsl.js +5 -5
- package/package.json +4 -3
- package/src/lib/shader-module/shader-module.ts +4 -4
- package/src/lib/wgsl/get-shader-layout-wgsl.ts +5 -5
- package/dist/libs/wgsl-reflect/wgsl_reflect.module.d.ts +0 -1112
- package/dist/libs/wgsl-reflect/wgsl_reflect.module.d.ts.map +0 -1
- package/dist/libs/wgsl-reflect/wgsl_reflect.module.js +0 -3389
- package/src/libs/wgsl-reflect/wgsl_reflect.module.js +0 -3394
- package/src/libs/wgsl-reflect/wgsl_reflect.module.js.map +0 -1
|
@@ -1,3389 +0,0 @@
|
|
|
1
|
-
// This file is copied from Brendan Duncan's https://github.com/brendan-duncan/wgsl_reflect
|
|
2
|
-
// under MIT license.
|
|
3
|
-
// @ts-nocheck
|
|
4
|
-
/* eslint-disable */
|
|
5
|
-
class ParseContext {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.constants = new Map();
|
|
8
|
-
this.aliases = new Map();
|
|
9
|
-
this.structs = new Map();
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* @class Node
|
|
14
|
-
* @category AST
|
|
15
|
-
* Base class for AST nodes parsed from a WGSL shader.
|
|
16
|
-
*/
|
|
17
|
-
class Node {
|
|
18
|
-
constructor() { }
|
|
19
|
-
get isAstNode() {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
get astNodeType() {
|
|
23
|
-
return "";
|
|
24
|
-
}
|
|
25
|
-
evaluate(context) {
|
|
26
|
-
throw new Error("Cannot evaluate node");
|
|
27
|
-
}
|
|
28
|
-
evaluateString(context) {
|
|
29
|
-
return this.evaluate(context).toString();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* @class Statement
|
|
34
|
-
* @extends Node
|
|
35
|
-
* @category AST
|
|
36
|
-
*/
|
|
37
|
-
class Statement extends Node {
|
|
38
|
-
constructor() {
|
|
39
|
-
super();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* @class Function
|
|
44
|
-
* @extends Statement
|
|
45
|
-
* @category AST
|
|
46
|
-
*/
|
|
47
|
-
class Function extends Statement {
|
|
48
|
-
constructor(name, args, returnType, body) {
|
|
49
|
-
super();
|
|
50
|
-
this.name = name;
|
|
51
|
-
this.args = args;
|
|
52
|
-
this.returnType = returnType;
|
|
53
|
-
this.body = body;
|
|
54
|
-
}
|
|
55
|
-
get astNodeType() {
|
|
56
|
-
return "function";
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* @class StaticAssert
|
|
61
|
-
* @extends Statement
|
|
62
|
-
* @category AST
|
|
63
|
-
*/
|
|
64
|
-
class StaticAssert extends Statement {
|
|
65
|
-
constructor(expression) {
|
|
66
|
-
super();
|
|
67
|
-
this.expression = expression;
|
|
68
|
-
}
|
|
69
|
-
get astNodeType() {
|
|
70
|
-
return "staticAssert";
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* @class While
|
|
75
|
-
* @extends Statement
|
|
76
|
-
* @category AST
|
|
77
|
-
*/
|
|
78
|
-
class While extends Statement {
|
|
79
|
-
constructor(condition, body) {
|
|
80
|
-
super();
|
|
81
|
-
this.condition = condition;
|
|
82
|
-
this.body = body;
|
|
83
|
-
}
|
|
84
|
-
get astNodeType() {
|
|
85
|
-
return "while";
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* @class Continuing
|
|
90
|
-
* @extends Statement
|
|
91
|
-
* @category AST
|
|
92
|
-
*/
|
|
93
|
-
class Continuing extends Statement {
|
|
94
|
-
constructor(body) {
|
|
95
|
-
super();
|
|
96
|
-
this.body = body;
|
|
97
|
-
}
|
|
98
|
-
get astNodeType() {
|
|
99
|
-
return "continuing";
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* @class For
|
|
104
|
-
* @extends Statement
|
|
105
|
-
* @category AST
|
|
106
|
-
*/
|
|
107
|
-
class For extends Statement {
|
|
108
|
-
constructor(init, condition, increment, body) {
|
|
109
|
-
super();
|
|
110
|
-
this.init = init;
|
|
111
|
-
this.condition = condition;
|
|
112
|
-
this.increment = increment;
|
|
113
|
-
this.body = body;
|
|
114
|
-
}
|
|
115
|
-
get astNodeType() {
|
|
116
|
-
return "for";
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* @class Var
|
|
121
|
-
* @extends Statement
|
|
122
|
-
* @category AST
|
|
123
|
-
*/
|
|
124
|
-
class Var extends Statement {
|
|
125
|
-
constructor(name, type, storage, access, value) {
|
|
126
|
-
super();
|
|
127
|
-
this.name = name;
|
|
128
|
-
this.type = type;
|
|
129
|
-
this.storage = storage;
|
|
130
|
-
this.access = access;
|
|
131
|
-
this.value = value;
|
|
132
|
-
}
|
|
133
|
-
get astNodeType() {
|
|
134
|
-
return "var";
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* @class Override
|
|
139
|
-
* @extends Statement
|
|
140
|
-
* @category AST
|
|
141
|
-
*/
|
|
142
|
-
class Override extends Statement {
|
|
143
|
-
constructor(name, type, value) {
|
|
144
|
-
super();
|
|
145
|
-
this.name = name;
|
|
146
|
-
this.type = type;
|
|
147
|
-
this.value = value;
|
|
148
|
-
}
|
|
149
|
-
get astNodeType() {
|
|
150
|
-
return "override";
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* @class Let
|
|
155
|
-
* @extends Statement
|
|
156
|
-
* @category AST
|
|
157
|
-
*/
|
|
158
|
-
class Let extends Statement {
|
|
159
|
-
constructor(name, type, storage, access, value) {
|
|
160
|
-
super();
|
|
161
|
-
this.name = name;
|
|
162
|
-
this.type = type;
|
|
163
|
-
this.storage = storage;
|
|
164
|
-
this.access = access;
|
|
165
|
-
this.value = value;
|
|
166
|
-
}
|
|
167
|
-
get astNodeType() {
|
|
168
|
-
return "let";
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* @class Const
|
|
173
|
-
* @extends Statement
|
|
174
|
-
* @category AST
|
|
175
|
-
*/
|
|
176
|
-
class Const extends Statement {
|
|
177
|
-
constructor(name, type, storage, access, value) {
|
|
178
|
-
super();
|
|
179
|
-
this.name = name;
|
|
180
|
-
this.type = type;
|
|
181
|
-
this.storage = storage;
|
|
182
|
-
this.access = access;
|
|
183
|
-
this.value = value;
|
|
184
|
-
}
|
|
185
|
-
get astNodeType() {
|
|
186
|
-
return "const";
|
|
187
|
-
}
|
|
188
|
-
evaluate(context) {
|
|
189
|
-
return this.value.evaluate(context);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
var IncrementOperator;
|
|
193
|
-
(function (IncrementOperator) {
|
|
194
|
-
IncrementOperator["increment"] = "++";
|
|
195
|
-
IncrementOperator["decrement"] = "--";
|
|
196
|
-
})(IncrementOperator || (IncrementOperator = {}));
|
|
197
|
-
(function (IncrementOperator) {
|
|
198
|
-
function parse(val) {
|
|
199
|
-
const key = val;
|
|
200
|
-
if (key == "parse")
|
|
201
|
-
throw new Error("Invalid value for IncrementOperator");
|
|
202
|
-
return IncrementOperator[key];
|
|
203
|
-
}
|
|
204
|
-
IncrementOperator.parse = parse;
|
|
205
|
-
})(IncrementOperator || (IncrementOperator = {}));
|
|
206
|
-
/**
|
|
207
|
-
* @class Increment
|
|
208
|
-
* @extends Statement
|
|
209
|
-
* @category AST
|
|
210
|
-
*/
|
|
211
|
-
class Increment extends Statement {
|
|
212
|
-
constructor(operator, variable) {
|
|
213
|
-
super();
|
|
214
|
-
this.operator = operator;
|
|
215
|
-
this.variable = variable;
|
|
216
|
-
}
|
|
217
|
-
get astNodeType() {
|
|
218
|
-
return "increment";
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
var AssignOperator;
|
|
222
|
-
(function (AssignOperator) {
|
|
223
|
-
AssignOperator["assign"] = "=";
|
|
224
|
-
AssignOperator["addAssign"] = "+=";
|
|
225
|
-
AssignOperator["subtractAssin"] = "-=";
|
|
226
|
-
AssignOperator["multiplyAssign"] = "*=";
|
|
227
|
-
AssignOperator["divideAssign"] = "/=";
|
|
228
|
-
AssignOperator["moduloAssign"] = "%=";
|
|
229
|
-
AssignOperator["andAssign"] = "&=";
|
|
230
|
-
AssignOperator["orAssign"] = "|=";
|
|
231
|
-
AssignOperator["xorAssign"] = "^=";
|
|
232
|
-
AssignOperator["shiftLeftAssign"] = "<<=";
|
|
233
|
-
AssignOperator["shiftRightAssign"] = ">>=";
|
|
234
|
-
})(AssignOperator || (AssignOperator = {}));
|
|
235
|
-
(function (AssignOperator) {
|
|
236
|
-
function parse(val) {
|
|
237
|
-
const key = val;
|
|
238
|
-
if (key == "parse")
|
|
239
|
-
throw new Error("Invalid value for AssignOperator");
|
|
240
|
-
return AssignOperator[key];
|
|
241
|
-
}
|
|
242
|
-
AssignOperator.parse = parse;
|
|
243
|
-
})(AssignOperator || (AssignOperator = {}));
|
|
244
|
-
/**
|
|
245
|
-
* @class Assign
|
|
246
|
-
* @extends Statement
|
|
247
|
-
* @category AST
|
|
248
|
-
*/
|
|
249
|
-
class Assign extends Statement {
|
|
250
|
-
constructor(operator, variable, value) {
|
|
251
|
-
super();
|
|
252
|
-
this.operator = operator;
|
|
253
|
-
this.variable = variable;
|
|
254
|
-
this.value = value;
|
|
255
|
-
}
|
|
256
|
-
get astNodeType() {
|
|
257
|
-
return "assign";
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* @class Call
|
|
262
|
-
* @extends Statement
|
|
263
|
-
* @category AST
|
|
264
|
-
*/
|
|
265
|
-
class Call extends Statement {
|
|
266
|
-
constructor(name, args) {
|
|
267
|
-
super();
|
|
268
|
-
this.name = name;
|
|
269
|
-
this.args = args;
|
|
270
|
-
}
|
|
271
|
-
get astNodeType() {
|
|
272
|
-
return "call";
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* @class Loop
|
|
277
|
-
* @extends Statement
|
|
278
|
-
* @category AST
|
|
279
|
-
*/
|
|
280
|
-
class Loop extends Statement {
|
|
281
|
-
constructor(body, continuing) {
|
|
282
|
-
super();
|
|
283
|
-
this.body = body;
|
|
284
|
-
this.continuing = continuing;
|
|
285
|
-
}
|
|
286
|
-
get astNodeType() {
|
|
287
|
-
return "loop";
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* @class Switch
|
|
292
|
-
* @extends Statement
|
|
293
|
-
* @category AST
|
|
294
|
-
*/
|
|
295
|
-
class Switch extends Statement {
|
|
296
|
-
constructor(condition, body) {
|
|
297
|
-
super();
|
|
298
|
-
this.condition = condition;
|
|
299
|
-
this.body = body;
|
|
300
|
-
}
|
|
301
|
-
get astNodeType() {
|
|
302
|
-
return "body";
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* @class If
|
|
307
|
-
* @extends Statement
|
|
308
|
-
* @category AST
|
|
309
|
-
*/
|
|
310
|
-
class If extends Statement {
|
|
311
|
-
constructor(condition, body, elseif, _else) {
|
|
312
|
-
super();
|
|
313
|
-
this.condition = condition;
|
|
314
|
-
this.body = body;
|
|
315
|
-
this.elseif = elseif;
|
|
316
|
-
this.else = _else;
|
|
317
|
-
}
|
|
318
|
-
get astNodeType() {
|
|
319
|
-
return "if";
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* @class Return
|
|
324
|
-
* @extends Statement
|
|
325
|
-
* @category AST
|
|
326
|
-
*/
|
|
327
|
-
class Return extends Statement {
|
|
328
|
-
constructor(value) {
|
|
329
|
-
super();
|
|
330
|
-
this.value = value;
|
|
331
|
-
}
|
|
332
|
-
get astNodeType() {
|
|
333
|
-
return "return";
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* @class Enable
|
|
338
|
-
* @extends Statement
|
|
339
|
-
* @category AST
|
|
340
|
-
*/
|
|
341
|
-
class Enable extends Statement {
|
|
342
|
-
constructor(name) {
|
|
343
|
-
super();
|
|
344
|
-
this.name = name;
|
|
345
|
-
}
|
|
346
|
-
get astNodeType() {
|
|
347
|
-
return "enable";
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* @class Alias
|
|
352
|
-
* @extends Statement
|
|
353
|
-
* @category AST
|
|
354
|
-
*/
|
|
355
|
-
class Alias extends Statement {
|
|
356
|
-
constructor(name, type) {
|
|
357
|
-
super();
|
|
358
|
-
this.name = name;
|
|
359
|
-
this.type = type;
|
|
360
|
-
}
|
|
361
|
-
get astNodeType() {
|
|
362
|
-
return "alias";
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* @class Discard
|
|
367
|
-
* @extends Statement
|
|
368
|
-
* @category AST
|
|
369
|
-
*/
|
|
370
|
-
class Discard extends Statement {
|
|
371
|
-
constructor() {
|
|
372
|
-
super();
|
|
373
|
-
}
|
|
374
|
-
get astNodeType() {
|
|
375
|
-
return "discard";
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* @class Break
|
|
380
|
-
* @extends Statement
|
|
381
|
-
* @category AST
|
|
382
|
-
*/
|
|
383
|
-
class Break extends Statement {
|
|
384
|
-
constructor() {
|
|
385
|
-
super();
|
|
386
|
-
}
|
|
387
|
-
get astNodeType() {
|
|
388
|
-
return "break";
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* @class Continue
|
|
393
|
-
* @extends Statement
|
|
394
|
-
* @category AST
|
|
395
|
-
*/
|
|
396
|
-
class Continue extends Statement {
|
|
397
|
-
constructor() {
|
|
398
|
-
super();
|
|
399
|
-
}
|
|
400
|
-
get astNodeType() {
|
|
401
|
-
return "continue";
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* @class Type
|
|
406
|
-
* @extends Statement
|
|
407
|
-
* @category AST
|
|
408
|
-
*/
|
|
409
|
-
class Type extends Statement {
|
|
410
|
-
constructor(name) {
|
|
411
|
-
super();
|
|
412
|
-
this.name = name;
|
|
413
|
-
}
|
|
414
|
-
get astNodeType() {
|
|
415
|
-
return "type";
|
|
416
|
-
}
|
|
417
|
-
get isStruct() {
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
|
-
get isArray() {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* @class StructType
|
|
426
|
-
* @extends Type
|
|
427
|
-
* @category AST
|
|
428
|
-
*/
|
|
429
|
-
class Struct extends Type {
|
|
430
|
-
constructor(name, members) {
|
|
431
|
-
super(name);
|
|
432
|
-
this.members = members;
|
|
433
|
-
}
|
|
434
|
-
get astNodeType() {
|
|
435
|
-
return "struct";
|
|
436
|
-
}
|
|
437
|
-
get isStruct() {
|
|
438
|
-
return true;
|
|
439
|
-
}
|
|
440
|
-
/// Return the index of the member with the given name, or -1 if not found.
|
|
441
|
-
getMemberIndex(name) {
|
|
442
|
-
for (let i = 0; i < this.members.length; i++) {
|
|
443
|
-
if (this.members[i].name == name)
|
|
444
|
-
return i;
|
|
445
|
-
}
|
|
446
|
-
return -1;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* @class TemplateType
|
|
451
|
-
* @extends Type
|
|
452
|
-
* @category AST
|
|
453
|
-
*/
|
|
454
|
-
class TemplateType extends Type {
|
|
455
|
-
constructor(name, format, access) {
|
|
456
|
-
super(name);
|
|
457
|
-
this.format = format;
|
|
458
|
-
this.access = access;
|
|
459
|
-
}
|
|
460
|
-
get astNodeType() {
|
|
461
|
-
return "template";
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* @class PointerType
|
|
466
|
-
* @extends Type
|
|
467
|
-
* @category AST
|
|
468
|
-
*/
|
|
469
|
-
class PointerType extends Type {
|
|
470
|
-
constructor(name, storage, type, access) {
|
|
471
|
-
super(name);
|
|
472
|
-
this.storage = storage;
|
|
473
|
-
this.type = type;
|
|
474
|
-
this.access = access;
|
|
475
|
-
}
|
|
476
|
-
get astNodeType() {
|
|
477
|
-
return "pointer";
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
/**
|
|
481
|
-
* @class ArrayType
|
|
482
|
-
* @extends Type
|
|
483
|
-
* @category AST
|
|
484
|
-
*/
|
|
485
|
-
class ArrayType extends Type {
|
|
486
|
-
constructor(name, attributes, format, count) {
|
|
487
|
-
super(name);
|
|
488
|
-
this.attributes = attributes;
|
|
489
|
-
this.format = format;
|
|
490
|
-
this.count = count;
|
|
491
|
-
}
|
|
492
|
-
get astNodeType() {
|
|
493
|
-
return "array";
|
|
494
|
-
}
|
|
495
|
-
get isArray() {
|
|
496
|
-
return true;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* @class SamplerType
|
|
501
|
-
* @extends Type
|
|
502
|
-
* @category AST
|
|
503
|
-
*/
|
|
504
|
-
class SamplerType extends Type {
|
|
505
|
-
constructor(name, format, access) {
|
|
506
|
-
super(name);
|
|
507
|
-
this.format = format;
|
|
508
|
-
this.access = access;
|
|
509
|
-
}
|
|
510
|
-
get astNodeType() {
|
|
511
|
-
return "sampler";
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* @class Expression
|
|
516
|
-
* @extends Node
|
|
517
|
-
* @category AST
|
|
518
|
-
*/
|
|
519
|
-
class Expression extends Node {
|
|
520
|
-
constructor() {
|
|
521
|
-
super();
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
/**
|
|
525
|
-
* @class StringExpr
|
|
526
|
-
* @extends Expression
|
|
527
|
-
* @category AST
|
|
528
|
-
*/
|
|
529
|
-
class StringExpr extends Expression {
|
|
530
|
-
constructor(value) {
|
|
531
|
-
super();
|
|
532
|
-
this.value = value;
|
|
533
|
-
}
|
|
534
|
-
get astNodeType() {
|
|
535
|
-
return "stringExpr";
|
|
536
|
-
}
|
|
537
|
-
toString() {
|
|
538
|
-
return this.value;
|
|
539
|
-
}
|
|
540
|
-
evaluateString() {
|
|
541
|
-
return this.value;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* @class CreateExpr
|
|
546
|
-
* @extends Expression
|
|
547
|
-
* @category AST
|
|
548
|
-
*/
|
|
549
|
-
class CreateExpr extends Expression {
|
|
550
|
-
constructor(type, args) {
|
|
551
|
-
super();
|
|
552
|
-
this.type = type;
|
|
553
|
-
this.args = args;
|
|
554
|
-
}
|
|
555
|
-
get astNodeType() {
|
|
556
|
-
return "createExpr";
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
/**
|
|
560
|
-
* @class CallExpr
|
|
561
|
-
* @extends Expression
|
|
562
|
-
* @category AST
|
|
563
|
-
*/
|
|
564
|
-
class CallExpr extends Expression {
|
|
565
|
-
constructor(name, args) {
|
|
566
|
-
super();
|
|
567
|
-
this.name = name;
|
|
568
|
-
this.args = args;
|
|
569
|
-
}
|
|
570
|
-
get astNodeType() {
|
|
571
|
-
return "callExpr";
|
|
572
|
-
}
|
|
573
|
-
evaluate(context) {
|
|
574
|
-
switch (this.name) {
|
|
575
|
-
case "abs":
|
|
576
|
-
return Math.abs(this.args[0].evaluate(context));
|
|
577
|
-
case "acos":
|
|
578
|
-
return Math.acos(this.args[0].evaluate(context));
|
|
579
|
-
case "acosh":
|
|
580
|
-
return Math.acosh(this.args[0].evaluate(context));
|
|
581
|
-
case "asin":
|
|
582
|
-
return Math.asin(this.args[0].evaluate(context));
|
|
583
|
-
case "asinh":
|
|
584
|
-
return Math.asinh(this.args[0].evaluate(context));
|
|
585
|
-
case "atan":
|
|
586
|
-
return Math.atan(this.args[0].evaluate(context));
|
|
587
|
-
case "atan2":
|
|
588
|
-
return Math.atan2(this.args[0].evaluate(context), this.args[1].evaluate(context));
|
|
589
|
-
case "atanh":
|
|
590
|
-
return Math.atanh(this.args[0].evaluate(context));
|
|
591
|
-
case "ceil":
|
|
592
|
-
return Math.ceil(this.args[0].evaluate(context));
|
|
593
|
-
case "clamp":
|
|
594
|
-
return Math.min(Math.max(this.args[0].evaluate(context), this.args[1].evaluate(context)), this.args[2].evaluate(context));
|
|
595
|
-
case "cos":
|
|
596
|
-
return Math.cos(this.args[0].evaluate(context));
|
|
597
|
-
//case "cross":
|
|
598
|
-
//TODO: (x[i] * y[j] - x[j] * y[i])
|
|
599
|
-
case "degrees":
|
|
600
|
-
return (this.args[0].evaluate(context) * 180) / Math.PI;
|
|
601
|
-
//case "determinant":
|
|
602
|
-
//TODO implement
|
|
603
|
-
case "distance":
|
|
604
|
-
return Math.sqrt(Math.pow(this.args[0].evaluate(context) - this.args[1].evaluate(context), 2));
|
|
605
|
-
case "dot":
|
|
606
|
-
//TODO: (x[i] * y[i])
|
|
607
|
-
case "exp":
|
|
608
|
-
return Math.exp(this.args[0].evaluate(context));
|
|
609
|
-
case "exp2":
|
|
610
|
-
return Math.pow(2, this.args[0].evaluate(context));
|
|
611
|
-
//case "extractBits":
|
|
612
|
-
//TODO: implement
|
|
613
|
-
//case "firstLeadingBit":
|
|
614
|
-
//TODO: implement
|
|
615
|
-
case "floor":
|
|
616
|
-
return Math.floor(this.args[0].evaluate(context));
|
|
617
|
-
case "fma":
|
|
618
|
-
return (this.args[0].evaluate(context) * this.args[1].evaluate(context) +
|
|
619
|
-
this.args[2].evaluate(context));
|
|
620
|
-
case "fract":
|
|
621
|
-
return (this.args[0].evaluate(context) -
|
|
622
|
-
Math.floor(this.args[0].evaluate(context)));
|
|
623
|
-
//case "frexp":
|
|
624
|
-
//TODO: implement
|
|
625
|
-
case "inverseSqrt":
|
|
626
|
-
return 1 / Math.sqrt(this.args[0].evaluate(context));
|
|
627
|
-
//case "length":
|
|
628
|
-
//TODO: implement
|
|
629
|
-
case "log":
|
|
630
|
-
return Math.log(this.args[0].evaluate(context));
|
|
631
|
-
case "log2":
|
|
632
|
-
return Math.log2(this.args[0].evaluate(context));
|
|
633
|
-
case "max":
|
|
634
|
-
return Math.max(this.args[0].evaluate(context), this.args[1].evaluate(context));
|
|
635
|
-
case "min":
|
|
636
|
-
return Math.min(this.args[0].evaluate(context), this.args[1].evaluate(context));
|
|
637
|
-
case "mix":
|
|
638
|
-
return (this.args[0].evaluate(context) *
|
|
639
|
-
(1 - this.args[2].evaluate(context)) +
|
|
640
|
-
this.args[1].evaluate(context) * this.args[2].evaluate(context));
|
|
641
|
-
case "modf":
|
|
642
|
-
return (this.args[0].evaluate(context) -
|
|
643
|
-
Math.floor(this.args[0].evaluate(context)));
|
|
644
|
-
case "pow":
|
|
645
|
-
return Math.pow(this.args[0].evaluate(context), this.args[1].evaluate(context));
|
|
646
|
-
case "radians":
|
|
647
|
-
return (this.args[0].evaluate(context) * Math.PI) / 180;
|
|
648
|
-
case "round":
|
|
649
|
-
return Math.round(this.args[0].evaluate(context));
|
|
650
|
-
case "sign":
|
|
651
|
-
return Math.sign(this.args[0].evaluate(context));
|
|
652
|
-
case "sin":
|
|
653
|
-
return Math.sin(this.args[0].evaluate(context));
|
|
654
|
-
case "sinh":
|
|
655
|
-
return Math.sinh(this.args[0].evaluate(context));
|
|
656
|
-
case "saturate":
|
|
657
|
-
return Math.min(Math.max(this.args[0].evaluate(context), 0), 1);
|
|
658
|
-
case "smoothstep":
|
|
659
|
-
return (this.args[0].evaluate(context) *
|
|
660
|
-
this.args[0].evaluate(context) *
|
|
661
|
-
(3 - 2 * this.args[0].evaluate(context)));
|
|
662
|
-
case "sqrt":
|
|
663
|
-
return Math.sqrt(this.args[0].evaluate(context));
|
|
664
|
-
case "step":
|
|
665
|
-
return this.args[0].evaluate(context) < this.args[1].evaluate(context)
|
|
666
|
-
? 0
|
|
667
|
-
: 1;
|
|
668
|
-
case "tan":
|
|
669
|
-
return Math.tan(this.args[0].evaluate(context));
|
|
670
|
-
case "tanh":
|
|
671
|
-
return Math.tanh(this.args[0].evaluate(context));
|
|
672
|
-
case "trunc":
|
|
673
|
-
return Math.trunc(this.args[0].evaluate(context));
|
|
674
|
-
default:
|
|
675
|
-
throw new Error("Non const function: " + this.name);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* @class VariableExpr
|
|
681
|
-
* @extends Expression
|
|
682
|
-
* @category AST
|
|
683
|
-
*/
|
|
684
|
-
class VariableExpr extends Expression {
|
|
685
|
-
constructor(name) {
|
|
686
|
-
super();
|
|
687
|
-
this.name = name;
|
|
688
|
-
}
|
|
689
|
-
get astNodeType() {
|
|
690
|
-
return "varExpr";
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
/**
|
|
694
|
-
* @class ConstExpr
|
|
695
|
-
* @extends Expression
|
|
696
|
-
* @category AST
|
|
697
|
-
*/
|
|
698
|
-
class ConstExpr extends Expression {
|
|
699
|
-
constructor(name, initializer) {
|
|
700
|
-
super();
|
|
701
|
-
this.name = name;
|
|
702
|
-
this.initializer = initializer;
|
|
703
|
-
}
|
|
704
|
-
get astNodeType() {
|
|
705
|
-
return "constExpr";
|
|
706
|
-
}
|
|
707
|
-
evaluate(context) {
|
|
708
|
-
var _a, _b;
|
|
709
|
-
if (this.initializer instanceof CreateExpr) {
|
|
710
|
-
// This is a struct constant
|
|
711
|
-
const property = (_a = this.postfix) === null || _a === void 0 ? void 0 : _a.evaluateString(context);
|
|
712
|
-
const type = (_b = this.initializer.type) === null || _b === void 0 ? void 0 : _b.name;
|
|
713
|
-
const struct = context.structs.get(type);
|
|
714
|
-
const memberIndex = struct === null || struct === void 0 ? void 0 : struct.getMemberIndex(property);
|
|
715
|
-
if (memberIndex != -1) {
|
|
716
|
-
const value = this.initializer.args[memberIndex].evaluate(context);
|
|
717
|
-
return value;
|
|
718
|
-
}
|
|
719
|
-
console.log(memberIndex);
|
|
720
|
-
}
|
|
721
|
-
return this.initializer.evaluate(context);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
/**
|
|
725
|
-
* @class LiteralExpr
|
|
726
|
-
* @extends Expression
|
|
727
|
-
* @category AST
|
|
728
|
-
*/
|
|
729
|
-
class LiteralExpr extends Expression {
|
|
730
|
-
constructor(value) {
|
|
731
|
-
super();
|
|
732
|
-
this.value = value;
|
|
733
|
-
}
|
|
734
|
-
get astNodeType() {
|
|
735
|
-
return "literalExpr";
|
|
736
|
-
}
|
|
737
|
-
evaluate() {
|
|
738
|
-
return this.value;
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
/**
|
|
742
|
-
* @class BitcastExpr
|
|
743
|
-
* @extends Expression
|
|
744
|
-
* @category AST
|
|
745
|
-
*/
|
|
746
|
-
class BitcastExpr extends Expression {
|
|
747
|
-
constructor(type, value) {
|
|
748
|
-
super();
|
|
749
|
-
this.type = type;
|
|
750
|
-
this.value = value;
|
|
751
|
-
}
|
|
752
|
-
get astNodeType() {
|
|
753
|
-
return "bitcastExpr";
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
/**
|
|
757
|
-
* @class TypecastExpr
|
|
758
|
-
* @extends Expression
|
|
759
|
-
* @category AST
|
|
760
|
-
*/
|
|
761
|
-
class TypecastExpr extends Expression {
|
|
762
|
-
constructor(type, args) {
|
|
763
|
-
super();
|
|
764
|
-
this.type = type;
|
|
765
|
-
this.args = args;
|
|
766
|
-
}
|
|
767
|
-
get astNodeType() {
|
|
768
|
-
return "typecastExpr";
|
|
769
|
-
}
|
|
770
|
-
evaluate(context) {
|
|
771
|
-
return this.args[0].evaluate(context);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* @class GroupingExpr
|
|
776
|
-
* @extends Expression
|
|
777
|
-
* @category AST
|
|
778
|
-
*/
|
|
779
|
-
class GroupingExpr extends Expression {
|
|
780
|
-
constructor(contents) {
|
|
781
|
-
super();
|
|
782
|
-
this.contents = contents;
|
|
783
|
-
}
|
|
784
|
-
get astNodeType() {
|
|
785
|
-
return "groupExpr";
|
|
786
|
-
}
|
|
787
|
-
evaluate(context) {
|
|
788
|
-
return this.contents[0].evaluate(context);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
/**
|
|
792
|
-
* @class Operator
|
|
793
|
-
* @extends Expression
|
|
794
|
-
* @category AST
|
|
795
|
-
*/
|
|
796
|
-
class Operator extends Expression {
|
|
797
|
-
constructor() {
|
|
798
|
-
super();
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* @class UnaryOperator
|
|
803
|
-
* @extends Operator
|
|
804
|
-
* @category AST
|
|
805
|
-
* @property {string} operator +, -, !, ~
|
|
806
|
-
*/
|
|
807
|
-
class UnaryOperator extends Operator {
|
|
808
|
-
constructor(operator, right) {
|
|
809
|
-
super();
|
|
810
|
-
this.operator = operator;
|
|
811
|
-
this.right = right;
|
|
812
|
-
}
|
|
813
|
-
get astNodeType() {
|
|
814
|
-
return "unaryOp";
|
|
815
|
-
}
|
|
816
|
-
evaluate(context) {
|
|
817
|
-
switch (this.operator) {
|
|
818
|
-
case "+":
|
|
819
|
-
return this.right.evaluate(context);
|
|
820
|
-
case "-":
|
|
821
|
-
return -this.right.evaluate(context);
|
|
822
|
-
case "!":
|
|
823
|
-
return this.right.evaluate(context) ? 0 : 1;
|
|
824
|
-
case "~":
|
|
825
|
-
return ~this.right.evaluate(context);
|
|
826
|
-
default:
|
|
827
|
-
throw new Error("Unknown unary operator: " + this.operator);
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* @class BinaryOperator
|
|
833
|
-
* @extends Operator
|
|
834
|
-
* @category AST
|
|
835
|
-
* @property {string} operator +, -, *, /, %, ==, !=, <, >, <=, >=, &&, ||
|
|
836
|
-
*/
|
|
837
|
-
class BinaryOperator extends Operator {
|
|
838
|
-
constructor(operator, left, right) {
|
|
839
|
-
super();
|
|
840
|
-
this.operator = operator;
|
|
841
|
-
this.left = left;
|
|
842
|
-
this.right = right;
|
|
843
|
-
}
|
|
844
|
-
get astNodeType() {
|
|
845
|
-
return "binaryOp";
|
|
846
|
-
}
|
|
847
|
-
evaluate(context) {
|
|
848
|
-
switch (this.operator) {
|
|
849
|
-
case "+":
|
|
850
|
-
return this.left.evaluate(context) + this.right.evaluate(context);
|
|
851
|
-
case "-":
|
|
852
|
-
return this.left.evaluate(context) - this.right.evaluate(context);
|
|
853
|
-
case "*":
|
|
854
|
-
return this.left.evaluate(context) * this.right.evaluate(context);
|
|
855
|
-
case "/":
|
|
856
|
-
return this.left.evaluate(context) / this.right.evaluate(context);
|
|
857
|
-
case "%":
|
|
858
|
-
return this.left.evaluate(context) % this.right.evaluate(context);
|
|
859
|
-
case "==":
|
|
860
|
-
return this.left.evaluate(context) == this.right.evaluate(context)
|
|
861
|
-
? 1
|
|
862
|
-
: 0;
|
|
863
|
-
case "!=":
|
|
864
|
-
return this.left.evaluate(context) != this.right.evaluate(context)
|
|
865
|
-
? 1
|
|
866
|
-
: 0;
|
|
867
|
-
case "<":
|
|
868
|
-
return this.left.evaluate(context) < this.right.evaluate(context)
|
|
869
|
-
? 1
|
|
870
|
-
: 0;
|
|
871
|
-
case ">":
|
|
872
|
-
return this.left.evaluate(context) > this.right.evaluate(context)
|
|
873
|
-
? 1
|
|
874
|
-
: 0;
|
|
875
|
-
case "<=":
|
|
876
|
-
return this.left.evaluate(context) <= this.right.evaluate(context)
|
|
877
|
-
? 1
|
|
878
|
-
: 0;
|
|
879
|
-
case ">=":
|
|
880
|
-
return this.left.evaluate(context) >= this.right.evaluate(context)
|
|
881
|
-
? 1
|
|
882
|
-
: 0;
|
|
883
|
-
case "&&":
|
|
884
|
-
return this.left.evaluate(context) && this.right.evaluate(context)
|
|
885
|
-
? 1
|
|
886
|
-
: 0;
|
|
887
|
-
case "||":
|
|
888
|
-
return this.left.evaluate(context) || this.right.evaluate(context)
|
|
889
|
-
? 1
|
|
890
|
-
: 0;
|
|
891
|
-
default:
|
|
892
|
-
throw new Error(`Unknown operator ${this.operator}`);
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
/**
|
|
897
|
-
* @class SwitchCase
|
|
898
|
-
* @extends Node
|
|
899
|
-
* @category AST
|
|
900
|
-
*/
|
|
901
|
-
class SwitchCase extends Node {
|
|
902
|
-
constructor() {
|
|
903
|
-
super();
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
/**
|
|
907
|
-
* @class Case
|
|
908
|
-
* @extends SwitchCase
|
|
909
|
-
* @category AST
|
|
910
|
-
*/
|
|
911
|
-
class Case extends SwitchCase {
|
|
912
|
-
constructor(selector, body) {
|
|
913
|
-
super();
|
|
914
|
-
this.selector = selector;
|
|
915
|
-
this.body = body;
|
|
916
|
-
}
|
|
917
|
-
get astNodeType() {
|
|
918
|
-
return "case";
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
/**
|
|
922
|
-
* @class Default
|
|
923
|
-
* @extends SwitchCase
|
|
924
|
-
* @category AST
|
|
925
|
-
*/
|
|
926
|
-
class Default extends SwitchCase {
|
|
927
|
-
constructor(body) {
|
|
928
|
-
super();
|
|
929
|
-
this.body = body;
|
|
930
|
-
}
|
|
931
|
-
get astNodeType() {
|
|
932
|
-
return "default";
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
/**
|
|
936
|
-
* @class Argument
|
|
937
|
-
* @extends Node
|
|
938
|
-
* @category AST
|
|
939
|
-
*/
|
|
940
|
-
class Argument extends Node {
|
|
941
|
-
constructor(name, type, attributes) {
|
|
942
|
-
super();
|
|
943
|
-
this.name = name;
|
|
944
|
-
this.type = type;
|
|
945
|
-
this.attributes = attributes;
|
|
946
|
-
}
|
|
947
|
-
get astNodeType() {
|
|
948
|
-
return "argument";
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* @class ElseIf
|
|
953
|
-
* @extends Node
|
|
954
|
-
* @category AST
|
|
955
|
-
*/
|
|
956
|
-
class ElseIf extends Node {
|
|
957
|
-
constructor(condition, body) {
|
|
958
|
-
super();
|
|
959
|
-
this.condition = condition;
|
|
960
|
-
this.body = body;
|
|
961
|
-
}
|
|
962
|
-
get astNodeType() {
|
|
963
|
-
return "elseif";
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
/**
|
|
967
|
-
* @class Member
|
|
968
|
-
* @extends Node
|
|
969
|
-
* @category AST
|
|
970
|
-
*/
|
|
971
|
-
class Member extends Node {
|
|
972
|
-
constructor(name, type, attributes) {
|
|
973
|
-
super();
|
|
974
|
-
this.name = name;
|
|
975
|
-
this.type = type;
|
|
976
|
-
this.attributes = attributes;
|
|
977
|
-
}
|
|
978
|
-
get astNodeType() {
|
|
979
|
-
return "member";
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* @class Attribute
|
|
984
|
-
* @extends Node
|
|
985
|
-
* @category AST
|
|
986
|
-
*/
|
|
987
|
-
class Attribute extends Node {
|
|
988
|
-
constructor(name, value) {
|
|
989
|
-
super();
|
|
990
|
-
this.name = name;
|
|
991
|
-
this.value = value;
|
|
992
|
-
}
|
|
993
|
-
get astNodeType() {
|
|
994
|
-
return "attribute";
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
var _a;
|
|
998
|
-
var TokenClass;
|
|
999
|
-
(function (TokenClass) {
|
|
1000
|
-
TokenClass[TokenClass["token"] = 0] = "token";
|
|
1001
|
-
TokenClass[TokenClass["keyword"] = 1] = "keyword";
|
|
1002
|
-
TokenClass[TokenClass["reserved"] = 2] = "reserved";
|
|
1003
|
-
})(TokenClass || (TokenClass = {}));
|
|
1004
|
-
class TokenType {
|
|
1005
|
-
constructor(name, type, rule) {
|
|
1006
|
-
this.name = name;
|
|
1007
|
-
this.type = type;
|
|
1008
|
-
this.rule = rule;
|
|
1009
|
-
}
|
|
1010
|
-
toString() {
|
|
1011
|
-
return this.name;
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
/// Catalog of defined token types, keywords, and reserved words.
|
|
1015
|
-
class TokenTypes {
|
|
1016
|
-
}
|
|
1017
|
-
_a = TokenTypes;
|
|
1018
|
-
TokenTypes.none = new TokenType("", TokenClass.reserved, "");
|
|
1019
|
-
TokenTypes.eof = new TokenType("EOF", TokenClass.token, "");
|
|
1020
|
-
TokenTypes.reserved = {
|
|
1021
|
-
asm: new TokenType("asm", TokenClass.reserved, "asm"),
|
|
1022
|
-
bf16: new TokenType("bf16", TokenClass.reserved, "bf16"),
|
|
1023
|
-
do: new TokenType("do", TokenClass.reserved, "do"),
|
|
1024
|
-
enum: new TokenType("enum", TokenClass.reserved, "enum"),
|
|
1025
|
-
f16: new TokenType("f16", TokenClass.reserved, "f16"),
|
|
1026
|
-
f64: new TokenType("f64", TokenClass.reserved, "f64"),
|
|
1027
|
-
handle: new TokenType("handle", TokenClass.reserved, "handle"),
|
|
1028
|
-
i8: new TokenType("i8", TokenClass.reserved, "i8"),
|
|
1029
|
-
i16: new TokenType("i16", TokenClass.reserved, "i16"),
|
|
1030
|
-
i64: new TokenType("i64", TokenClass.reserved, "i64"),
|
|
1031
|
-
mat: new TokenType("mat", TokenClass.reserved, "mat"),
|
|
1032
|
-
premerge: new TokenType("premerge", TokenClass.reserved, "premerge"),
|
|
1033
|
-
regardless: new TokenType("regardless", TokenClass.reserved, "regardless"),
|
|
1034
|
-
typedef: new TokenType("typedef", TokenClass.reserved, "typedef"),
|
|
1035
|
-
u8: new TokenType("u8", TokenClass.reserved, "u8"),
|
|
1036
|
-
u16: new TokenType("u16", TokenClass.reserved, "u16"),
|
|
1037
|
-
u64: new TokenType("u64", TokenClass.reserved, "u64"),
|
|
1038
|
-
unless: new TokenType("unless", TokenClass.reserved, "unless"),
|
|
1039
|
-
using: new TokenType("using", TokenClass.reserved, "using"),
|
|
1040
|
-
vec: new TokenType("vec", TokenClass.reserved, "vec"),
|
|
1041
|
-
void: new TokenType("void", TokenClass.reserved, "void"),
|
|
1042
|
-
};
|
|
1043
|
-
TokenTypes.keywords = {
|
|
1044
|
-
array: new TokenType("array", TokenClass.keyword, "array"),
|
|
1045
|
-
atomic: new TokenType("atomic", TokenClass.keyword, "atomic"),
|
|
1046
|
-
bool: new TokenType("bool", TokenClass.keyword, "bool"),
|
|
1047
|
-
f32: new TokenType("f32", TokenClass.keyword, "f32"),
|
|
1048
|
-
i32: new TokenType("i32", TokenClass.keyword, "i32"),
|
|
1049
|
-
mat2x2: new TokenType("mat2x2", TokenClass.keyword, "mat2x2"),
|
|
1050
|
-
mat2x3: new TokenType("mat2x3", TokenClass.keyword, "mat2x3"),
|
|
1051
|
-
mat2x4: new TokenType("mat2x4", TokenClass.keyword, "mat2x4"),
|
|
1052
|
-
mat3x2: new TokenType("mat3x2", TokenClass.keyword, "mat3x2"),
|
|
1053
|
-
mat3x3: new TokenType("mat3x3", TokenClass.keyword, "mat3x3"),
|
|
1054
|
-
mat3x4: new TokenType("mat3x4", TokenClass.keyword, "mat3x4"),
|
|
1055
|
-
mat4x2: new TokenType("mat4x2", TokenClass.keyword, "mat4x2"),
|
|
1056
|
-
mat4x3: new TokenType("mat4x3", TokenClass.keyword, "mat4x3"),
|
|
1057
|
-
mat4x4: new TokenType("mat4x4", TokenClass.keyword, "mat4x4"),
|
|
1058
|
-
ptr: new TokenType("ptr", TokenClass.keyword, "ptr"),
|
|
1059
|
-
sampler: new TokenType("sampler", TokenClass.keyword, "sampler"),
|
|
1060
|
-
sampler_comparison: new TokenType("sampler_comparison", TokenClass.keyword, "sampler_comparison"),
|
|
1061
|
-
struct: new TokenType("struct", TokenClass.keyword, "struct"),
|
|
1062
|
-
texture_1d: new TokenType("texture_1d", TokenClass.keyword, "texture_1d"),
|
|
1063
|
-
texture_2d: new TokenType("texture_2d", TokenClass.keyword, "texture_2d"),
|
|
1064
|
-
texture_2d_array: new TokenType("texture_2d_array", TokenClass.keyword, "texture_2d_array"),
|
|
1065
|
-
texture_3d: new TokenType("texture_3d", TokenClass.keyword, "texture_3d"),
|
|
1066
|
-
texture_cube: new TokenType("texture_cube", TokenClass.keyword, "texture_cube"),
|
|
1067
|
-
texture_cube_array: new TokenType("texture_cube_array", TokenClass.keyword, "texture_cube_array"),
|
|
1068
|
-
texture_multisampled_2d: new TokenType("texture_multisampled_2d", TokenClass.keyword, "texture_multisampled_2d"),
|
|
1069
|
-
texture_storage_1d: new TokenType("texture_storage_1d", TokenClass.keyword, "texture_storage_1d"),
|
|
1070
|
-
texture_storage_2d: new TokenType("texture_storage_2d", TokenClass.keyword, "texture_storage_2d"),
|
|
1071
|
-
texture_storage_2d_array: new TokenType("texture_storage_2d_array", TokenClass.keyword, "texture_storage_2d_array"),
|
|
1072
|
-
texture_storage_3d: new TokenType("texture_storage_3d", TokenClass.keyword, "texture_storage_3d"),
|
|
1073
|
-
texture_depth_2d: new TokenType("texture_depth_2d", TokenClass.keyword, "texture_depth_2d"),
|
|
1074
|
-
texture_depth_2d_array: new TokenType("texture_depth_2d_array", TokenClass.keyword, "texture_depth_2d_array"),
|
|
1075
|
-
texture_depth_cube: new TokenType("texture_depth_cube", TokenClass.keyword, "texture_depth_cube"),
|
|
1076
|
-
texture_depth_cube_array: new TokenType("texture_depth_cube_array", TokenClass.keyword, "texture_depth_cube_array"),
|
|
1077
|
-
texture_depth_multisampled_2d: new TokenType("texture_depth_multisampled_2d", TokenClass.keyword, "texture_depth_multisampled_2d"),
|
|
1078
|
-
texture_external: new TokenType("texture_external", TokenClass.keyword, "texture_external"),
|
|
1079
|
-
u32: new TokenType("u32", TokenClass.keyword, "u32"),
|
|
1080
|
-
vec2: new TokenType("vec2", TokenClass.keyword, "vec2"),
|
|
1081
|
-
vec3: new TokenType("vec3", TokenClass.keyword, "vec3"),
|
|
1082
|
-
vec4: new TokenType("vec4", TokenClass.keyword, "vec4"),
|
|
1083
|
-
bitcast: new TokenType("bitcast", TokenClass.keyword, "bitcast"),
|
|
1084
|
-
block: new TokenType("block", TokenClass.keyword, "block"),
|
|
1085
|
-
break: new TokenType("break", TokenClass.keyword, "break"),
|
|
1086
|
-
case: new TokenType("case", TokenClass.keyword, "case"),
|
|
1087
|
-
continue: new TokenType("continue", TokenClass.keyword, "continue"),
|
|
1088
|
-
continuing: new TokenType("continuing", TokenClass.keyword, "continuing"),
|
|
1089
|
-
default: new TokenType("default", TokenClass.keyword, "default"),
|
|
1090
|
-
discard: new TokenType("discard", TokenClass.keyword, "discard"),
|
|
1091
|
-
else: new TokenType("else", TokenClass.keyword, "else"),
|
|
1092
|
-
enable: new TokenType("enable", TokenClass.keyword, "enable"),
|
|
1093
|
-
fallthrough: new TokenType("fallthrough", TokenClass.keyword, "fallthrough"),
|
|
1094
|
-
false: new TokenType("false", TokenClass.keyword, "false"),
|
|
1095
|
-
fn: new TokenType("fn", TokenClass.keyword, "fn"),
|
|
1096
|
-
for: new TokenType("for", TokenClass.keyword, "for"),
|
|
1097
|
-
function: new TokenType("function", TokenClass.keyword, "function"),
|
|
1098
|
-
if: new TokenType("if", TokenClass.keyword, "if"),
|
|
1099
|
-
let: new TokenType("let", TokenClass.keyword, "let"),
|
|
1100
|
-
const: new TokenType("const", TokenClass.keyword, "const"),
|
|
1101
|
-
loop: new TokenType("loop", TokenClass.keyword, "loop"),
|
|
1102
|
-
while: new TokenType("while", TokenClass.keyword, "while"),
|
|
1103
|
-
private: new TokenType("private", TokenClass.keyword, "private"),
|
|
1104
|
-
read: new TokenType("read", TokenClass.keyword, "read"),
|
|
1105
|
-
read_write: new TokenType("read_write", TokenClass.keyword, "read_write"),
|
|
1106
|
-
return: new TokenType("return", TokenClass.keyword, "return"),
|
|
1107
|
-
storage: new TokenType("storage", TokenClass.keyword, "storage"),
|
|
1108
|
-
switch: new TokenType("switch", TokenClass.keyword, "switch"),
|
|
1109
|
-
true: new TokenType("true", TokenClass.keyword, "true"),
|
|
1110
|
-
alias: new TokenType("alias", TokenClass.keyword, "alias"),
|
|
1111
|
-
type: new TokenType("type", TokenClass.keyword, "type"),
|
|
1112
|
-
uniform: new TokenType("uniform", TokenClass.keyword, "uniform"),
|
|
1113
|
-
var: new TokenType("var", TokenClass.keyword, "var"),
|
|
1114
|
-
override: new TokenType("override", TokenClass.keyword, "override"),
|
|
1115
|
-
workgroup: new TokenType("workgroup", TokenClass.keyword, "workgroup"),
|
|
1116
|
-
write: new TokenType("write", TokenClass.keyword, "write"),
|
|
1117
|
-
r8unorm: new TokenType("r8unorm", TokenClass.keyword, "r8unorm"),
|
|
1118
|
-
r8snorm: new TokenType("r8snorm", TokenClass.keyword, "r8snorm"),
|
|
1119
|
-
r8uint: new TokenType("r8uint", TokenClass.keyword, "r8uint"),
|
|
1120
|
-
r8sint: new TokenType("r8sint", TokenClass.keyword, "r8sint"),
|
|
1121
|
-
r16uint: new TokenType("r16uint", TokenClass.keyword, "r16uint"),
|
|
1122
|
-
r16sint: new TokenType("r16sint", TokenClass.keyword, "r16sint"),
|
|
1123
|
-
r16float: new TokenType("r16float", TokenClass.keyword, "r16float"),
|
|
1124
|
-
rg8unorm: new TokenType("rg8unorm", TokenClass.keyword, "rg8unorm"),
|
|
1125
|
-
rg8snorm: new TokenType("rg8snorm", TokenClass.keyword, "rg8snorm"),
|
|
1126
|
-
rg8uint: new TokenType("rg8uint", TokenClass.keyword, "rg8uint"),
|
|
1127
|
-
rg8sint: new TokenType("rg8sint", TokenClass.keyword, "rg8sint"),
|
|
1128
|
-
r32uint: new TokenType("r32uint", TokenClass.keyword, "r32uint"),
|
|
1129
|
-
r32sint: new TokenType("r32sint", TokenClass.keyword, "r32sint"),
|
|
1130
|
-
r32float: new TokenType("r32float", TokenClass.keyword, "r32float"),
|
|
1131
|
-
rg16uint: new TokenType("rg16uint", TokenClass.keyword, "rg16uint"),
|
|
1132
|
-
rg16sint: new TokenType("rg16sint", TokenClass.keyword, "rg16sint"),
|
|
1133
|
-
rg16float: new TokenType("rg16float", TokenClass.keyword, "rg16float"),
|
|
1134
|
-
rgba8unorm: new TokenType("rgba8unorm", TokenClass.keyword, "rgba8unorm"),
|
|
1135
|
-
rgba8unorm_srgb: new TokenType("rgba8unorm_srgb", TokenClass.keyword, "rgba8unorm_srgb"),
|
|
1136
|
-
rgba8snorm: new TokenType("rgba8snorm", TokenClass.keyword, "rgba8snorm"),
|
|
1137
|
-
rgba8uint: new TokenType("rgba8uint", TokenClass.keyword, "rgba8uint"),
|
|
1138
|
-
rgba8sint: new TokenType("rgba8sint", TokenClass.keyword, "rgba8sint"),
|
|
1139
|
-
bgra8unorm: new TokenType("bgra8unorm", TokenClass.keyword, "bgra8unorm"),
|
|
1140
|
-
bgra8unorm_srgb: new TokenType("bgra8unorm_srgb", TokenClass.keyword, "bgra8unorm_srgb"),
|
|
1141
|
-
rgb10a2unorm: new TokenType("rgb10a2unorm", TokenClass.keyword, "rgb10a2unorm"),
|
|
1142
|
-
rg11b10float: new TokenType("rg11b10float", TokenClass.keyword, "rg11b10float"),
|
|
1143
|
-
rg32uint: new TokenType("rg32uint", TokenClass.keyword, "rg32uint"),
|
|
1144
|
-
rg32sint: new TokenType("rg32sint", TokenClass.keyword, "rg32sint"),
|
|
1145
|
-
rg32float: new TokenType("rg32float", TokenClass.keyword, "rg32float"),
|
|
1146
|
-
rgba16uint: new TokenType("rgba16uint", TokenClass.keyword, "rgba16uint"),
|
|
1147
|
-
rgba16sint: new TokenType("rgba16sint", TokenClass.keyword, "rgba16sint"),
|
|
1148
|
-
rgba16float: new TokenType("rgba16float", TokenClass.keyword, "rgba16float"),
|
|
1149
|
-
rgba32uint: new TokenType("rgba32uint", TokenClass.keyword, "rgba32uint"),
|
|
1150
|
-
rgba32sint: new TokenType("rgba32sint", TokenClass.keyword, "rgba32sint"),
|
|
1151
|
-
rgba32float: new TokenType("rgba32float", TokenClass.keyword, "rgba32float"),
|
|
1152
|
-
static_assert: new TokenType("static_assert", TokenClass.keyword, "static_assert"),
|
|
1153
|
-
// WGSL grammar has a few keywords that have different token names than the strings they
|
|
1154
|
-
// represent. Aliasing them here.
|
|
1155
|
-
/*int32: new TokenType("i32", TokenClass.keyword, "i32"),
|
|
1156
|
-
uint32: new TokenType("u32", TokenClass.keyword, "u32"),
|
|
1157
|
-
float32: new TokenType("f32", TokenClass.keyword, "f32"),
|
|
1158
|
-
pointer: new TokenType("ptr", TokenClass.keyword, "ptr"),*/
|
|
1159
|
-
};
|
|
1160
|
-
TokenTypes.tokens = {
|
|
1161
|
-
decimal_float_literal: new TokenType("decimal_float_literal", TokenClass.token, /((-?[0-9]*\.[0-9]+|-?[0-9]+\.[0-9]*)((e|E)(\+|-)?[0-9]+)?f?)|(-?[0-9]+(e|E)(\+|-)?[0-9]+f?)|([0-9]+f)/),
|
|
1162
|
-
hex_float_literal: new TokenType("hex_float_literal", TokenClass.token, /-?0x((([0-9a-fA-F]*\.[0-9a-fA-F]+|[0-9a-fA-F]+\.[0-9a-fA-F]*)((p|P)(\+|-)?[0-9]+f?)?)|([0-9a-fA-F]+(p|P)(\+|-)?[0-9]+f?))/),
|
|
1163
|
-
int_literal: new TokenType("int_literal", TokenClass.token, /-?0x[0-9a-fA-F]+|0i?|-?[1-9][0-9]*i?/),
|
|
1164
|
-
uint_literal: new TokenType("uint_literal", TokenClass.token, /0x[0-9a-fA-F]+u|0u|[1-9][0-9]*u/),
|
|
1165
|
-
ident: new TokenType("ident", TokenClass.token, /[a-zA-Z][0-9a-zA-Z_]*/),
|
|
1166
|
-
and: new TokenType("and", TokenClass.token, "&"),
|
|
1167
|
-
and_and: new TokenType("and_and", TokenClass.token, "&&"),
|
|
1168
|
-
arrow: new TokenType("arrow ", TokenClass.token, "->"),
|
|
1169
|
-
attr: new TokenType("attr", TokenClass.token, "@"),
|
|
1170
|
-
attr_left: new TokenType("attr_left", TokenClass.token, "[["),
|
|
1171
|
-
attr_right: new TokenType("attr_right", TokenClass.token, "]]"),
|
|
1172
|
-
forward_slash: new TokenType("forward_slash", TokenClass.token, "/"),
|
|
1173
|
-
bang: new TokenType("bang", TokenClass.token, "!"),
|
|
1174
|
-
bracket_left: new TokenType("bracket_left", TokenClass.token, "["),
|
|
1175
|
-
bracket_right: new TokenType("bracket_right", TokenClass.token, "]"),
|
|
1176
|
-
brace_left: new TokenType("brace_left", TokenClass.token, "{"),
|
|
1177
|
-
brace_right: new TokenType("brace_right", TokenClass.token, "}"),
|
|
1178
|
-
colon: new TokenType("colon", TokenClass.token, ":"),
|
|
1179
|
-
comma: new TokenType("comma", TokenClass.token, ","),
|
|
1180
|
-
equal: new TokenType("equal", TokenClass.token, "="),
|
|
1181
|
-
equal_equal: new TokenType("equal_equal", TokenClass.token, "=="),
|
|
1182
|
-
not_equal: new TokenType("not_equal", TokenClass.token, "!="),
|
|
1183
|
-
greater_than: new TokenType("greater_than", TokenClass.token, ">"),
|
|
1184
|
-
greater_than_equal: new TokenType("greater_than_equal", TokenClass.token, ">="),
|
|
1185
|
-
shift_right: new TokenType("shift_right", TokenClass.token, ">>"),
|
|
1186
|
-
less_than: new TokenType("less_than", TokenClass.token, "<"),
|
|
1187
|
-
less_than_equal: new TokenType("less_than_equal", TokenClass.token, "<="),
|
|
1188
|
-
shift_left: new TokenType("shift_left", TokenClass.token, "<<"),
|
|
1189
|
-
modulo: new TokenType("modulo", TokenClass.token, "%"),
|
|
1190
|
-
minus: new TokenType("minus", TokenClass.token, "-"),
|
|
1191
|
-
minus_minus: new TokenType("minus_minus", TokenClass.token, "--"),
|
|
1192
|
-
period: new TokenType("period", TokenClass.token, "."),
|
|
1193
|
-
plus: new TokenType("plus", TokenClass.token, "+"),
|
|
1194
|
-
plus_plus: new TokenType("plus_plus", TokenClass.token, "++"),
|
|
1195
|
-
or: new TokenType("or", TokenClass.token, "|"),
|
|
1196
|
-
or_or: new TokenType("or_or", TokenClass.token, "||"),
|
|
1197
|
-
paren_left: new TokenType("paren_left", TokenClass.token, "("),
|
|
1198
|
-
paren_right: new TokenType("paren_right", TokenClass.token, ")"),
|
|
1199
|
-
semicolon: new TokenType("semicolon", TokenClass.token, ";"),
|
|
1200
|
-
star: new TokenType("star", TokenClass.token, "*"),
|
|
1201
|
-
tilde: new TokenType("tilde", TokenClass.token, "~"),
|
|
1202
|
-
underscore: new TokenType("underscore", TokenClass.token, "_"),
|
|
1203
|
-
xor: new TokenType("xor", TokenClass.token, "^"),
|
|
1204
|
-
plus_equal: new TokenType("plus_equal", TokenClass.token, "+="),
|
|
1205
|
-
minus_equal: new TokenType("minus_equal", TokenClass.token, "-="),
|
|
1206
|
-
times_equal: new TokenType("times_equal", TokenClass.token, "*="),
|
|
1207
|
-
division_equal: new TokenType("division_equal", TokenClass.token, "/="),
|
|
1208
|
-
modulo_equal: new TokenType("modulo_equal", TokenClass.token, "%="),
|
|
1209
|
-
and_equal: new TokenType("and_equal", TokenClass.token, "&="),
|
|
1210
|
-
or_equal: new TokenType("or_equal", TokenClass.token, "|="),
|
|
1211
|
-
xor_equal: new TokenType("xor_equal", TokenClass.token, "^="),
|
|
1212
|
-
shift_right_equal: new TokenType("shift_right_equal", TokenClass.token, ">>="),
|
|
1213
|
-
shift_left_equal: new TokenType("shift_left_equal", TokenClass.token, "<<="),
|
|
1214
|
-
};
|
|
1215
|
-
TokenTypes.storage_class = [
|
|
1216
|
-
_a.keywords.function,
|
|
1217
|
-
_a.keywords.private,
|
|
1218
|
-
_a.keywords.workgroup,
|
|
1219
|
-
_a.keywords.uniform,
|
|
1220
|
-
_a.keywords.storage,
|
|
1221
|
-
];
|
|
1222
|
-
TokenTypes.access_mode = [
|
|
1223
|
-
_a.keywords.read,
|
|
1224
|
-
_a.keywords.write,
|
|
1225
|
-
_a.keywords.read_write,
|
|
1226
|
-
];
|
|
1227
|
-
TokenTypes.sampler_type = [
|
|
1228
|
-
_a.keywords.sampler,
|
|
1229
|
-
_a.keywords.sampler_comparison,
|
|
1230
|
-
];
|
|
1231
|
-
TokenTypes.sampled_texture_type = [
|
|
1232
|
-
_a.keywords.texture_1d,
|
|
1233
|
-
_a.keywords.texture_2d,
|
|
1234
|
-
_a.keywords.texture_2d_array,
|
|
1235
|
-
_a.keywords.texture_3d,
|
|
1236
|
-
_a.keywords.texture_cube,
|
|
1237
|
-
_a.keywords.texture_cube_array,
|
|
1238
|
-
];
|
|
1239
|
-
TokenTypes.multisampled_texture_type = [
|
|
1240
|
-
_a.keywords.texture_multisampled_2d,
|
|
1241
|
-
];
|
|
1242
|
-
TokenTypes.storage_texture_type = [
|
|
1243
|
-
_a.keywords.texture_storage_1d,
|
|
1244
|
-
_a.keywords.texture_storage_2d,
|
|
1245
|
-
_a.keywords.texture_storage_2d_array,
|
|
1246
|
-
_a.keywords.texture_storage_3d,
|
|
1247
|
-
];
|
|
1248
|
-
TokenTypes.depth_texture_type = [
|
|
1249
|
-
_a.keywords.texture_depth_2d,
|
|
1250
|
-
_a.keywords.texture_depth_2d_array,
|
|
1251
|
-
_a.keywords.texture_depth_cube,
|
|
1252
|
-
_a.keywords.texture_depth_cube_array,
|
|
1253
|
-
_a.keywords.texture_depth_multisampled_2d,
|
|
1254
|
-
];
|
|
1255
|
-
TokenTypes.texture_external_type = [_a.keywords.texture_external];
|
|
1256
|
-
TokenTypes.any_texture_type = [
|
|
1257
|
-
..._a.sampled_texture_type,
|
|
1258
|
-
..._a.multisampled_texture_type,
|
|
1259
|
-
..._a.storage_texture_type,
|
|
1260
|
-
..._a.depth_texture_type,
|
|
1261
|
-
..._a.texture_external_type,
|
|
1262
|
-
];
|
|
1263
|
-
TokenTypes.texel_format = [
|
|
1264
|
-
_a.keywords.r8unorm,
|
|
1265
|
-
_a.keywords.r8snorm,
|
|
1266
|
-
_a.keywords.r8uint,
|
|
1267
|
-
_a.keywords.r8sint,
|
|
1268
|
-
_a.keywords.r16uint,
|
|
1269
|
-
_a.keywords.r16sint,
|
|
1270
|
-
_a.keywords.r16float,
|
|
1271
|
-
_a.keywords.rg8unorm,
|
|
1272
|
-
_a.keywords.rg8snorm,
|
|
1273
|
-
_a.keywords.rg8uint,
|
|
1274
|
-
_a.keywords.rg8sint,
|
|
1275
|
-
_a.keywords.r32uint,
|
|
1276
|
-
_a.keywords.r32sint,
|
|
1277
|
-
_a.keywords.r32float,
|
|
1278
|
-
_a.keywords.rg16uint,
|
|
1279
|
-
_a.keywords.rg16sint,
|
|
1280
|
-
_a.keywords.rg16float,
|
|
1281
|
-
_a.keywords.rgba8unorm,
|
|
1282
|
-
_a.keywords.rgba8unorm_srgb,
|
|
1283
|
-
_a.keywords.rgba8snorm,
|
|
1284
|
-
_a.keywords.rgba8uint,
|
|
1285
|
-
_a.keywords.rgba8sint,
|
|
1286
|
-
_a.keywords.bgra8unorm,
|
|
1287
|
-
_a.keywords.bgra8unorm_srgb,
|
|
1288
|
-
_a.keywords.rgb10a2unorm,
|
|
1289
|
-
_a.keywords.rg11b10float,
|
|
1290
|
-
_a.keywords.rg32uint,
|
|
1291
|
-
_a.keywords.rg32sint,
|
|
1292
|
-
_a.keywords.rg32float,
|
|
1293
|
-
_a.keywords.rgba16uint,
|
|
1294
|
-
_a.keywords.rgba16sint,
|
|
1295
|
-
_a.keywords.rgba16float,
|
|
1296
|
-
_a.keywords.rgba32uint,
|
|
1297
|
-
_a.keywords.rgba32sint,
|
|
1298
|
-
_a.keywords.rgba32float,
|
|
1299
|
-
];
|
|
1300
|
-
TokenTypes.const_literal = [
|
|
1301
|
-
_a.tokens.int_literal,
|
|
1302
|
-
_a.tokens.uint_literal,
|
|
1303
|
-
_a.tokens.decimal_float_literal,
|
|
1304
|
-
_a.tokens.hex_float_literal,
|
|
1305
|
-
_a.keywords.true,
|
|
1306
|
-
_a.keywords.false,
|
|
1307
|
-
];
|
|
1308
|
-
TokenTypes.literal_or_ident = [
|
|
1309
|
-
_a.tokens.ident,
|
|
1310
|
-
_a.tokens.int_literal,
|
|
1311
|
-
_a.tokens.uint_literal,
|
|
1312
|
-
_a.tokens.decimal_float_literal,
|
|
1313
|
-
_a.tokens.hex_float_literal,
|
|
1314
|
-
];
|
|
1315
|
-
TokenTypes.element_count_expression = [
|
|
1316
|
-
_a.tokens.int_literal,
|
|
1317
|
-
_a.tokens.uint_literal,
|
|
1318
|
-
_a.tokens.ident,
|
|
1319
|
-
];
|
|
1320
|
-
TokenTypes.template_types = [
|
|
1321
|
-
_a.keywords.vec2,
|
|
1322
|
-
_a.keywords.vec3,
|
|
1323
|
-
_a.keywords.vec4,
|
|
1324
|
-
_a.keywords.mat2x2,
|
|
1325
|
-
_a.keywords.mat2x3,
|
|
1326
|
-
_a.keywords.mat2x4,
|
|
1327
|
-
_a.keywords.mat3x2,
|
|
1328
|
-
_a.keywords.mat3x3,
|
|
1329
|
-
_a.keywords.mat3x4,
|
|
1330
|
-
_a.keywords.mat4x2,
|
|
1331
|
-
_a.keywords.mat4x3,
|
|
1332
|
-
_a.keywords.mat4x4,
|
|
1333
|
-
_a.keywords.atomic,
|
|
1334
|
-
_a.keywords.bitcast,
|
|
1335
|
-
..._a.any_texture_type,
|
|
1336
|
-
];
|
|
1337
|
-
// The grammar calls out 'block', but attribute grammar is defined to use a 'ident'.
|
|
1338
|
-
// The attribute grammar should be ident | block.
|
|
1339
|
-
TokenTypes.attribute_name = [_a.tokens.ident, _a.keywords.block];
|
|
1340
|
-
TokenTypes.assignment_operators = [
|
|
1341
|
-
_a.tokens.equal,
|
|
1342
|
-
_a.tokens.plus_equal,
|
|
1343
|
-
_a.tokens.minus_equal,
|
|
1344
|
-
_a.tokens.times_equal,
|
|
1345
|
-
_a.tokens.division_equal,
|
|
1346
|
-
_a.tokens.modulo_equal,
|
|
1347
|
-
_a.tokens.and_equal,
|
|
1348
|
-
_a.tokens.or_equal,
|
|
1349
|
-
_a.tokens.xor_equal,
|
|
1350
|
-
_a.tokens.shift_right_equal,
|
|
1351
|
-
_a.tokens.shift_left_equal,
|
|
1352
|
-
];
|
|
1353
|
-
TokenTypes.increment_operators = [
|
|
1354
|
-
_a.tokens.plus_plus,
|
|
1355
|
-
_a.tokens.minus_minus,
|
|
1356
|
-
];
|
|
1357
|
-
/// A token parsed by the WgslScanner.
|
|
1358
|
-
class Token {
|
|
1359
|
-
constructor(type, lexeme, line) {
|
|
1360
|
-
this.type = type;
|
|
1361
|
-
this.lexeme = lexeme;
|
|
1362
|
-
this.line = line;
|
|
1363
|
-
}
|
|
1364
|
-
toString() {
|
|
1365
|
-
return this.lexeme;
|
|
1366
|
-
}
|
|
1367
|
-
isTemplateType() {
|
|
1368
|
-
return TokenTypes.template_types.indexOf(this.type) != -1;
|
|
1369
|
-
}
|
|
1370
|
-
isArrayType() {
|
|
1371
|
-
return this.type == TokenTypes.keywords.array;
|
|
1372
|
-
}
|
|
1373
|
-
isArrayOrTemplateType() {
|
|
1374
|
-
return this.isArrayType() || this.isTemplateType();
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
/// Lexical scanner for the WGSL language. This takes an input source text and generates a list
|
|
1378
|
-
/// of Token objects, which can then be fed into the WgslParser to generate an AST.
|
|
1379
|
-
class WgslScanner {
|
|
1380
|
-
constructor(source) {
|
|
1381
|
-
this._tokens = [];
|
|
1382
|
-
this._start = 0;
|
|
1383
|
-
this._current = 0;
|
|
1384
|
-
this._line = 1;
|
|
1385
|
-
this._source = source !== null && source !== void 0 ? source : "";
|
|
1386
|
-
}
|
|
1387
|
-
/// Scan all tokens from the source.
|
|
1388
|
-
scanTokens() {
|
|
1389
|
-
while (!this._isAtEnd()) {
|
|
1390
|
-
this._start = this._current;
|
|
1391
|
-
if (!this.scanToken())
|
|
1392
|
-
throw `Invalid syntax at line ${this._line}`;
|
|
1393
|
-
}
|
|
1394
|
-
this._tokens.push(new Token(TokenTypes.eof, "", this._line));
|
|
1395
|
-
return this._tokens;
|
|
1396
|
-
}
|
|
1397
|
-
/// Scan a single token from the source.
|
|
1398
|
-
scanToken() {
|
|
1399
|
-
// Find the longest consecutive set of characters that match a rule.
|
|
1400
|
-
let lexeme = this._advance();
|
|
1401
|
-
// Skip line-feed, adding to the line counter.
|
|
1402
|
-
if (lexeme == "\n") {
|
|
1403
|
-
this._line++;
|
|
1404
|
-
return true;
|
|
1405
|
-
}
|
|
1406
|
-
// Skip whitespace
|
|
1407
|
-
if (this._isWhitespace(lexeme)) {
|
|
1408
|
-
return true;
|
|
1409
|
-
}
|
|
1410
|
-
if (lexeme == "/") {
|
|
1411
|
-
// If it's a // comment, skip everything until the next line-feed.
|
|
1412
|
-
if (this._peekAhead() == "/") {
|
|
1413
|
-
while (lexeme != "\n") {
|
|
1414
|
-
if (this._isAtEnd())
|
|
1415
|
-
return true;
|
|
1416
|
-
lexeme = this._advance();
|
|
1417
|
-
}
|
|
1418
|
-
// skip the linefeed
|
|
1419
|
-
this._line++;
|
|
1420
|
-
return true;
|
|
1421
|
-
}
|
|
1422
|
-
else if (this._peekAhead() == "*") {
|
|
1423
|
-
// If it's a / * block comment, skip everything until the matching * /,
|
|
1424
|
-
// allowing for nested block comments.
|
|
1425
|
-
this._advance();
|
|
1426
|
-
let commentLevel = 1;
|
|
1427
|
-
while (commentLevel > 0) {
|
|
1428
|
-
if (this._isAtEnd())
|
|
1429
|
-
return true;
|
|
1430
|
-
lexeme = this._advance();
|
|
1431
|
-
if (lexeme == "\n") {
|
|
1432
|
-
this._line++;
|
|
1433
|
-
}
|
|
1434
|
-
else if (lexeme == "*") {
|
|
1435
|
-
if (this._peekAhead() == "/") {
|
|
1436
|
-
this._advance();
|
|
1437
|
-
commentLevel--;
|
|
1438
|
-
if (commentLevel == 0) {
|
|
1439
|
-
return true;
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
else if (lexeme == "/") {
|
|
1444
|
-
if (this._peekAhead() == "*") {
|
|
1445
|
-
this._advance();
|
|
1446
|
-
commentLevel++;
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
return true;
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
let matchType = TokenTypes.none;
|
|
1454
|
-
for (;;) {
|
|
1455
|
-
let matchedType = this._findType(lexeme);
|
|
1456
|
-
// An exception to "longest lexeme" rule is '>>'. In the case of 1>>2, it's a
|
|
1457
|
-
// shift_right.
|
|
1458
|
-
// In the case of array<vec4<f32>>, it's two greater_than's (one to close the vec4,
|
|
1459
|
-
// and one to close the array).
|
|
1460
|
-
// Another ambiguity is '>='. In the case of vec2<i32>=vec2(1,2),
|
|
1461
|
-
// it's a greather_than and an equal, not a greater_than_equal.
|
|
1462
|
-
// WGSL requires context sensitive parsing to resolve these ambiguities. Both of these cases
|
|
1463
|
-
// are predicated on it the > either closing a template, or being part of an operator.
|
|
1464
|
-
// The solution here is to check if there was a less_than up to some number of tokens
|
|
1465
|
-
// previously, and the token prior to that is a keyword that requires a '<', then it will be
|
|
1466
|
-
// split into two operators; otherwise it's a single operator.
|
|
1467
|
-
const nextLexeme = this._peekAhead();
|
|
1468
|
-
if (lexeme == ">" && (nextLexeme == ">" || nextLexeme == "=")) {
|
|
1469
|
-
let foundLessThan = false;
|
|
1470
|
-
let ti = this._tokens.length - 1;
|
|
1471
|
-
for (let count = 0; count < 5 && ti >= 0; ++count, --ti) {
|
|
1472
|
-
if (this._tokens[ti].type === TokenTypes.tokens.less_than) {
|
|
1473
|
-
if (ti > 0 && this._tokens[ti - 1].isArrayOrTemplateType()) {
|
|
1474
|
-
foundLessThan = true;
|
|
1475
|
-
}
|
|
1476
|
-
break;
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
// If there was a less_than in the recent token history, then this is probably a
|
|
1480
|
-
// greater_than.
|
|
1481
|
-
if (foundLessThan) {
|
|
1482
|
-
this._addToken(matchedType);
|
|
1483
|
-
return true;
|
|
1484
|
-
}
|
|
1485
|
-
}
|
|
1486
|
-
// The current lexeme may not match any rule, but some token types may be invalid for
|
|
1487
|
-
// part of the string but valid after a few more characters.
|
|
1488
|
-
// For example, 0x.5 is a hex_float_literal. But as it's being scanned,
|
|
1489
|
-
// "0" is a int_literal, then "0x" is invalid. If we stopped there, it would return
|
|
1490
|
-
// the int_literal "0", but that's incorrect. So if we look forward a few characters,
|
|
1491
|
-
// we'd get "0x.", which is still invalid, followed by "0x.5" which is the correct
|
|
1492
|
-
// hex_float_literal. So that means if we hit an non-matching string, we should look
|
|
1493
|
-
// ahead up to two characters to see if the string starts matching a valid rule again.
|
|
1494
|
-
if (matchedType === TokenTypes.none) {
|
|
1495
|
-
let lookAheadLexeme = lexeme;
|
|
1496
|
-
let lookAhead = 0;
|
|
1497
|
-
const maxLookAhead = 2;
|
|
1498
|
-
for (let li = 0; li < maxLookAhead; ++li) {
|
|
1499
|
-
lookAheadLexeme += this._peekAhead(li);
|
|
1500
|
-
matchedType = this._findType(lookAheadLexeme);
|
|
1501
|
-
if (matchedType !== TokenTypes.none) {
|
|
1502
|
-
lookAhead = li;
|
|
1503
|
-
break;
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
if (matchedType === TokenTypes.none) {
|
|
1507
|
-
if (matchType === TokenTypes.none)
|
|
1508
|
-
return false;
|
|
1509
|
-
this._current--;
|
|
1510
|
-
this._addToken(matchType);
|
|
1511
|
-
return true;
|
|
1512
|
-
}
|
|
1513
|
-
lexeme = lookAheadLexeme;
|
|
1514
|
-
this._current += lookAhead + 1;
|
|
1515
|
-
}
|
|
1516
|
-
matchType = matchedType;
|
|
1517
|
-
if (this._isAtEnd())
|
|
1518
|
-
break;
|
|
1519
|
-
lexeme += this._advance();
|
|
1520
|
-
}
|
|
1521
|
-
// We got to the end of the input stream. Then the token we've ready so far is it.
|
|
1522
|
-
if (matchType === TokenTypes.none)
|
|
1523
|
-
return false;
|
|
1524
|
-
this._addToken(matchType);
|
|
1525
|
-
return true;
|
|
1526
|
-
}
|
|
1527
|
-
_findType(lexeme) {
|
|
1528
|
-
for (const name in TokenTypes.keywords) {
|
|
1529
|
-
const type = TokenTypes.keywords[name];
|
|
1530
|
-
if (this._match(lexeme, type.rule)) {
|
|
1531
|
-
return type;
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
for (const name in TokenTypes.tokens) {
|
|
1535
|
-
const type = TokenTypes.tokens[name];
|
|
1536
|
-
if (this._match(lexeme, type.rule)) {
|
|
1537
|
-
return type;
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
return TokenTypes.none;
|
|
1541
|
-
}
|
|
1542
|
-
_match(lexeme, rule) {
|
|
1543
|
-
if (typeof rule === "string") {
|
|
1544
|
-
if (rule == lexeme) {
|
|
1545
|
-
return true;
|
|
1546
|
-
}
|
|
1547
|
-
}
|
|
1548
|
-
else {
|
|
1549
|
-
// regex
|
|
1550
|
-
const match = rule.exec(lexeme);
|
|
1551
|
-
if (match && match.index == 0 && match[0] == lexeme)
|
|
1552
|
-
return true;
|
|
1553
|
-
}
|
|
1554
|
-
return false;
|
|
1555
|
-
}
|
|
1556
|
-
_isAtEnd() {
|
|
1557
|
-
return this._current >= this._source.length;
|
|
1558
|
-
}
|
|
1559
|
-
_isWhitespace(c) {
|
|
1560
|
-
return c == " " || c == "\t" || c == "\r";
|
|
1561
|
-
}
|
|
1562
|
-
_advance(amount = 0) {
|
|
1563
|
-
let c = this._source[this._current];
|
|
1564
|
-
amount = amount || 0;
|
|
1565
|
-
amount++;
|
|
1566
|
-
this._current += amount;
|
|
1567
|
-
return c;
|
|
1568
|
-
}
|
|
1569
|
-
_peekAhead(offset = 0) {
|
|
1570
|
-
offset = offset || 0;
|
|
1571
|
-
if (this._current + offset >= this._source.length)
|
|
1572
|
-
return "\0";
|
|
1573
|
-
return this._source[this._current + offset];
|
|
1574
|
-
}
|
|
1575
|
-
_addToken(type) {
|
|
1576
|
-
const text = this._source.substring(this._start, this._current);
|
|
1577
|
-
this._tokens.push(new Token(type, text, this._line));
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
/**
|
|
1581
|
-
* @author Brendan Duncan / https://github.com/brendan-duncan
|
|
1582
|
-
*/
|
|
1583
|
-
/// Parse a sequence of tokens from the WgslScanner into an Abstract Syntax Tree (AST).
|
|
1584
|
-
class WgslParser {
|
|
1585
|
-
constructor() {
|
|
1586
|
-
this._tokens = [];
|
|
1587
|
-
this._current = 0;
|
|
1588
|
-
this._context = new ParseContext();
|
|
1589
|
-
}
|
|
1590
|
-
parse(tokensOrCode) {
|
|
1591
|
-
this._initialize(tokensOrCode);
|
|
1592
|
-
let statements = [];
|
|
1593
|
-
while (!this._isAtEnd()) {
|
|
1594
|
-
const statement = this._global_decl_or_directive();
|
|
1595
|
-
if (!statement)
|
|
1596
|
-
break;
|
|
1597
|
-
statements.push(statement);
|
|
1598
|
-
}
|
|
1599
|
-
return statements;
|
|
1600
|
-
}
|
|
1601
|
-
_initialize(tokensOrCode) {
|
|
1602
|
-
if (tokensOrCode) {
|
|
1603
|
-
if (typeof tokensOrCode == "string") {
|
|
1604
|
-
const scanner = new WgslScanner(tokensOrCode);
|
|
1605
|
-
this._tokens = scanner.scanTokens();
|
|
1606
|
-
}
|
|
1607
|
-
else {
|
|
1608
|
-
this._tokens = tokensOrCode;
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
else {
|
|
1612
|
-
this._tokens = [];
|
|
1613
|
-
}
|
|
1614
|
-
this._current = 0;
|
|
1615
|
-
}
|
|
1616
|
-
_error(token, message) {
|
|
1617
|
-
console.error(token, message);
|
|
1618
|
-
return {
|
|
1619
|
-
token,
|
|
1620
|
-
message,
|
|
1621
|
-
toString: function () {
|
|
1622
|
-
return `${message}`;
|
|
1623
|
-
},
|
|
1624
|
-
};
|
|
1625
|
-
}
|
|
1626
|
-
_isAtEnd() {
|
|
1627
|
-
return (this._current >= this._tokens.length ||
|
|
1628
|
-
this._peek().type == TokenTypes.eof);
|
|
1629
|
-
}
|
|
1630
|
-
_match(types) {
|
|
1631
|
-
if (types instanceof TokenType) {
|
|
1632
|
-
if (this._check(types)) {
|
|
1633
|
-
this._advance();
|
|
1634
|
-
return true;
|
|
1635
|
-
}
|
|
1636
|
-
return false;
|
|
1637
|
-
}
|
|
1638
|
-
for (let i = 0, l = types.length; i < l; ++i) {
|
|
1639
|
-
const type = types[i];
|
|
1640
|
-
if (this._check(type)) {
|
|
1641
|
-
this._advance();
|
|
1642
|
-
return true;
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
return false;
|
|
1646
|
-
}
|
|
1647
|
-
_consume(types, message) {
|
|
1648
|
-
if (this._check(types))
|
|
1649
|
-
return this._advance();
|
|
1650
|
-
throw this._error(this._peek(), message);
|
|
1651
|
-
}
|
|
1652
|
-
_check(types) {
|
|
1653
|
-
if (this._isAtEnd())
|
|
1654
|
-
return false;
|
|
1655
|
-
const tk = this._peek();
|
|
1656
|
-
if (types instanceof Array) {
|
|
1657
|
-
let t = tk.type;
|
|
1658
|
-
let index = types.indexOf(t);
|
|
1659
|
-
return index != -1;
|
|
1660
|
-
}
|
|
1661
|
-
return tk.type == types;
|
|
1662
|
-
}
|
|
1663
|
-
_advance() {
|
|
1664
|
-
if (!this._isAtEnd())
|
|
1665
|
-
this._current++;
|
|
1666
|
-
return this._previous();
|
|
1667
|
-
}
|
|
1668
|
-
_peek() {
|
|
1669
|
-
return this._tokens[this._current];
|
|
1670
|
-
}
|
|
1671
|
-
_previous() {
|
|
1672
|
-
return this._tokens[this._current - 1];
|
|
1673
|
-
}
|
|
1674
|
-
_global_decl_or_directive() {
|
|
1675
|
-
// semicolon
|
|
1676
|
-
// global_variable_decl semicolon
|
|
1677
|
-
// global_constant_decl semicolon
|
|
1678
|
-
// type_alias semicolon
|
|
1679
|
-
// struct_decl
|
|
1680
|
-
// function_decl
|
|
1681
|
-
// enable_directive
|
|
1682
|
-
// Ignore any stand-alone semicolons
|
|
1683
|
-
while (this._match(TokenTypes.tokens.semicolon) && !this._isAtEnd())
|
|
1684
|
-
;
|
|
1685
|
-
if (this._match(TokenTypes.keywords.alias)) {
|
|
1686
|
-
const type = this._type_alias();
|
|
1687
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'");
|
|
1688
|
-
return type;
|
|
1689
|
-
}
|
|
1690
|
-
if (this._match(TokenTypes.keywords.enable)) {
|
|
1691
|
-
const enable = this._enable_directive();
|
|
1692
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'");
|
|
1693
|
-
return enable;
|
|
1694
|
-
}
|
|
1695
|
-
// The following statements have an optional attribute*
|
|
1696
|
-
const attrs = this._attribute();
|
|
1697
|
-
if (this._check(TokenTypes.keywords.var)) {
|
|
1698
|
-
const _var = this._global_variable_decl();
|
|
1699
|
-
if (_var != null)
|
|
1700
|
-
_var.attributes = attrs;
|
|
1701
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
|
|
1702
|
-
return _var;
|
|
1703
|
-
}
|
|
1704
|
-
if (this._check(TokenTypes.keywords.override)) {
|
|
1705
|
-
const _override = this._override_variable_decl();
|
|
1706
|
-
if (_override != null)
|
|
1707
|
-
_override.attributes = attrs;
|
|
1708
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
|
|
1709
|
-
return _override;
|
|
1710
|
-
}
|
|
1711
|
-
if (this._check(TokenTypes.keywords.let)) {
|
|
1712
|
-
const _let = this._global_let_decl();
|
|
1713
|
-
if (_let != null)
|
|
1714
|
-
_let.attributes = attrs;
|
|
1715
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
|
|
1716
|
-
return _let;
|
|
1717
|
-
}
|
|
1718
|
-
if (this._check(TokenTypes.keywords.const)) {
|
|
1719
|
-
const _const = this._global_const_decl();
|
|
1720
|
-
if (_const != null)
|
|
1721
|
-
_const.attributes = attrs;
|
|
1722
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
|
|
1723
|
-
return _const;
|
|
1724
|
-
}
|
|
1725
|
-
if (this._check(TokenTypes.keywords.struct)) {
|
|
1726
|
-
const _struct = this._struct_decl();
|
|
1727
|
-
if (_struct != null)
|
|
1728
|
-
_struct.attributes = attrs;
|
|
1729
|
-
return _struct;
|
|
1730
|
-
}
|
|
1731
|
-
if (this._check(TokenTypes.keywords.fn)) {
|
|
1732
|
-
const _fn = this._function_decl();
|
|
1733
|
-
if (_fn != null)
|
|
1734
|
-
_fn.attributes = attrs;
|
|
1735
|
-
return _fn;
|
|
1736
|
-
}
|
|
1737
|
-
return null;
|
|
1738
|
-
}
|
|
1739
|
-
_function_decl() {
|
|
1740
|
-
// attribute* function_header compound_statement
|
|
1741
|
-
// function_header: fn ident paren_left param_list? paren_right (arrow attribute* type_decl)?
|
|
1742
|
-
if (!this._match(TokenTypes.keywords.fn))
|
|
1743
|
-
return null;
|
|
1744
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected function name.").toString();
|
|
1745
|
-
this._consume(TokenTypes.tokens.paren_left, "Expected '(' for function arguments.");
|
|
1746
|
-
const args = [];
|
|
1747
|
-
if (!this._check(TokenTypes.tokens.paren_right)) {
|
|
1748
|
-
do {
|
|
1749
|
-
if (this._check(TokenTypes.tokens.paren_right))
|
|
1750
|
-
break;
|
|
1751
|
-
const argAttrs = this._attribute();
|
|
1752
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected argument name.").toString();
|
|
1753
|
-
this._consume(TokenTypes.tokens.colon, "Expected ':' for argument type.");
|
|
1754
|
-
const typeAttrs = this._attribute();
|
|
1755
|
-
const type = this._type_decl();
|
|
1756
|
-
if (type != null) {
|
|
1757
|
-
type.attributes = typeAttrs;
|
|
1758
|
-
args.push(new Argument(name, type, argAttrs));
|
|
1759
|
-
}
|
|
1760
|
-
} while (this._match(TokenTypes.tokens.comma));
|
|
1761
|
-
}
|
|
1762
|
-
this._consume(TokenTypes.tokens.paren_right, "Expected ')' after function arguments.");
|
|
1763
|
-
let _return = null;
|
|
1764
|
-
if (this._match(TokenTypes.tokens.arrow)) {
|
|
1765
|
-
const attrs = this._attribute();
|
|
1766
|
-
_return = this._type_decl();
|
|
1767
|
-
if (_return != null)
|
|
1768
|
-
_return.attributes = attrs;
|
|
1769
|
-
}
|
|
1770
|
-
const body = this._compound_statement();
|
|
1771
|
-
return new Function(name, args, _return, body);
|
|
1772
|
-
}
|
|
1773
|
-
_compound_statement() {
|
|
1774
|
-
// brace_left statement* brace_right
|
|
1775
|
-
const statements = [];
|
|
1776
|
-
this._consume(TokenTypes.tokens.brace_left, "Expected '{' for block.");
|
|
1777
|
-
while (!this._check(TokenTypes.tokens.brace_right)) {
|
|
1778
|
-
const statement = this._statement();
|
|
1779
|
-
if (statement !== null)
|
|
1780
|
-
statements.push(statement);
|
|
1781
|
-
}
|
|
1782
|
-
this._consume(TokenTypes.tokens.brace_right, "Expected '}' for block.");
|
|
1783
|
-
return statements;
|
|
1784
|
-
}
|
|
1785
|
-
_statement() {
|
|
1786
|
-
// semicolon
|
|
1787
|
-
// return_statement semicolon
|
|
1788
|
-
// if_statement
|
|
1789
|
-
// switch_statement
|
|
1790
|
-
// loop_statement
|
|
1791
|
-
// for_statement
|
|
1792
|
-
// func_call_statement semicolon
|
|
1793
|
-
// variable_statement semicolon
|
|
1794
|
-
// break_statement semicolon
|
|
1795
|
-
// continue_statement semicolon
|
|
1796
|
-
// continuing_statement compound_statement
|
|
1797
|
-
// discard semicolon
|
|
1798
|
-
// assignment_statement semicolon
|
|
1799
|
-
// compound_statement
|
|
1800
|
-
// increment_statement semicolon
|
|
1801
|
-
// decrement_statement semicolon
|
|
1802
|
-
// static_assert_statement semicolon
|
|
1803
|
-
// Ignore any stand-alone semicolons
|
|
1804
|
-
while (this._match(TokenTypes.tokens.semicolon) && !this._isAtEnd())
|
|
1805
|
-
;
|
|
1806
|
-
if (this._check(TokenTypes.keywords.if))
|
|
1807
|
-
return this._if_statement();
|
|
1808
|
-
if (this._check(TokenTypes.keywords.switch))
|
|
1809
|
-
return this._switch_statement();
|
|
1810
|
-
if (this._check(TokenTypes.keywords.loop))
|
|
1811
|
-
return this._loop_statement();
|
|
1812
|
-
if (this._check(TokenTypes.keywords.for))
|
|
1813
|
-
return this._for_statement();
|
|
1814
|
-
if (this._check(TokenTypes.keywords.while))
|
|
1815
|
-
return this._while_statement();
|
|
1816
|
-
if (this._check(TokenTypes.keywords.continuing))
|
|
1817
|
-
return this._continuing_statement();
|
|
1818
|
-
if (this._check(TokenTypes.keywords.static_assert))
|
|
1819
|
-
return this._static_assert_statement();
|
|
1820
|
-
if (this._check(TokenTypes.tokens.brace_left))
|
|
1821
|
-
return this._compound_statement();
|
|
1822
|
-
let result = null;
|
|
1823
|
-
if (this._check(TokenTypes.keywords.return))
|
|
1824
|
-
result = this._return_statement();
|
|
1825
|
-
else if (this._check([
|
|
1826
|
-
TokenTypes.keywords.var,
|
|
1827
|
-
TokenTypes.keywords.let,
|
|
1828
|
-
TokenTypes.keywords.const,
|
|
1829
|
-
]))
|
|
1830
|
-
result = this._variable_statement();
|
|
1831
|
-
else if (this._match(TokenTypes.keywords.discard))
|
|
1832
|
-
result = new Discard();
|
|
1833
|
-
else if (this._match(TokenTypes.keywords.break))
|
|
1834
|
-
result = new Break();
|
|
1835
|
-
else if (this._match(TokenTypes.keywords.continue))
|
|
1836
|
-
result = new Continue();
|
|
1837
|
-
else
|
|
1838
|
-
result =
|
|
1839
|
-
this._increment_decrement_statement() ||
|
|
1840
|
-
this._func_call_statement() ||
|
|
1841
|
-
this._assignment_statement();
|
|
1842
|
-
if (result != null)
|
|
1843
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';' after statement.");
|
|
1844
|
-
return result;
|
|
1845
|
-
}
|
|
1846
|
-
_static_assert_statement() {
|
|
1847
|
-
if (!this._match(TokenTypes.keywords.static_assert))
|
|
1848
|
-
return null;
|
|
1849
|
-
let expression = this._optional_paren_expression();
|
|
1850
|
-
return new StaticAssert(expression);
|
|
1851
|
-
}
|
|
1852
|
-
_while_statement() {
|
|
1853
|
-
if (!this._match(TokenTypes.keywords.while))
|
|
1854
|
-
return null;
|
|
1855
|
-
let condition = this._optional_paren_expression();
|
|
1856
|
-
const block = this._compound_statement();
|
|
1857
|
-
return new While(condition, block);
|
|
1858
|
-
}
|
|
1859
|
-
_continuing_statement() {
|
|
1860
|
-
if (!this._match(TokenTypes.keywords.continuing))
|
|
1861
|
-
return null;
|
|
1862
|
-
const block = this._compound_statement();
|
|
1863
|
-
return new Continuing(block);
|
|
1864
|
-
}
|
|
1865
|
-
_for_statement() {
|
|
1866
|
-
// for paren_left for_header paren_right compound_statement
|
|
1867
|
-
if (!this._match(TokenTypes.keywords.for))
|
|
1868
|
-
return null;
|
|
1869
|
-
this._consume(TokenTypes.tokens.paren_left, "Expected '('.");
|
|
1870
|
-
// for_header: (variable_statement assignment_statement func_call_statement)? semicolon short_circuit_or_expression? semicolon (assignment_statement func_call_statement)?
|
|
1871
|
-
const init = !this._check(TokenTypes.tokens.semicolon)
|
|
1872
|
-
? this._for_init()
|
|
1873
|
-
: null;
|
|
1874
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
|
|
1875
|
-
const condition = !this._check(TokenTypes.tokens.semicolon)
|
|
1876
|
-
? this._short_circuit_or_expression()
|
|
1877
|
-
: null;
|
|
1878
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
|
|
1879
|
-
const increment = !this._check(TokenTypes.tokens.paren_right)
|
|
1880
|
-
? this._for_increment()
|
|
1881
|
-
: null;
|
|
1882
|
-
this._consume(TokenTypes.tokens.paren_right, "Expected ')'.");
|
|
1883
|
-
const body = this._compound_statement();
|
|
1884
|
-
return new For(init, condition, increment, body);
|
|
1885
|
-
}
|
|
1886
|
-
_for_init() {
|
|
1887
|
-
// (variable_statement assignment_statement func_call_statement)?
|
|
1888
|
-
return (this._variable_statement() ||
|
|
1889
|
-
this._func_call_statement() ||
|
|
1890
|
-
this._assignment_statement());
|
|
1891
|
-
}
|
|
1892
|
-
_for_increment() {
|
|
1893
|
-
// (assignment_statement func_call_statement increment_statement)?
|
|
1894
|
-
return (this._func_call_statement() ||
|
|
1895
|
-
this._increment_decrement_statement() ||
|
|
1896
|
-
this._assignment_statement());
|
|
1897
|
-
}
|
|
1898
|
-
_variable_statement() {
|
|
1899
|
-
// variable_decl
|
|
1900
|
-
// variable_decl equal short_circuit_or_expression
|
|
1901
|
-
// let (ident variable_ident_decl) equal short_circuit_or_expression
|
|
1902
|
-
// const (ident variable_ident_decl) equal short_circuit_or_expression
|
|
1903
|
-
if (this._check(TokenTypes.keywords.var)) {
|
|
1904
|
-
const _var = this._variable_decl();
|
|
1905
|
-
if (_var === null)
|
|
1906
|
-
throw this._error(this._peek(), "Variable declaration expected.");
|
|
1907
|
-
let value = null;
|
|
1908
|
-
if (this._match(TokenTypes.tokens.equal))
|
|
1909
|
-
value = this._short_circuit_or_expression();
|
|
1910
|
-
return new Var(_var.name, _var.type, _var.storage, _var.access, value);
|
|
1911
|
-
}
|
|
1912
|
-
if (this._match(TokenTypes.keywords.let)) {
|
|
1913
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected name for let.").toString();
|
|
1914
|
-
let type = null;
|
|
1915
|
-
if (this._match(TokenTypes.tokens.colon)) {
|
|
1916
|
-
const typeAttrs = this._attribute();
|
|
1917
|
-
type = this._type_decl();
|
|
1918
|
-
if (type != null)
|
|
1919
|
-
type.attributes = typeAttrs;
|
|
1920
|
-
}
|
|
1921
|
-
this._consume(TokenTypes.tokens.equal, "Expected '=' for let.");
|
|
1922
|
-
const value = this._short_circuit_or_expression();
|
|
1923
|
-
return new Let(name, type, null, null, value);
|
|
1924
|
-
}
|
|
1925
|
-
if (this._match(TokenTypes.keywords.const)) {
|
|
1926
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected name for const.").toString();
|
|
1927
|
-
let type = null;
|
|
1928
|
-
if (this._match(TokenTypes.tokens.colon)) {
|
|
1929
|
-
const typeAttrs = this._attribute();
|
|
1930
|
-
type = this._type_decl();
|
|
1931
|
-
if (type != null)
|
|
1932
|
-
type.attributes = typeAttrs;
|
|
1933
|
-
}
|
|
1934
|
-
this._consume(TokenTypes.tokens.equal, "Expected '=' for const.");
|
|
1935
|
-
const value = this._short_circuit_or_expression();
|
|
1936
|
-
return new Const(name, type, null, null, value);
|
|
1937
|
-
}
|
|
1938
|
-
return null;
|
|
1939
|
-
}
|
|
1940
|
-
_increment_decrement_statement() {
|
|
1941
|
-
const savedPos = this._current;
|
|
1942
|
-
const _var = this._unary_expression();
|
|
1943
|
-
if (_var == null)
|
|
1944
|
-
return null;
|
|
1945
|
-
if (!this._check(TokenTypes.increment_operators)) {
|
|
1946
|
-
this._current = savedPos;
|
|
1947
|
-
return null;
|
|
1948
|
-
}
|
|
1949
|
-
const token = this._consume(TokenTypes.increment_operators, "Expected increment operator");
|
|
1950
|
-
return new Increment(token.type === TokenTypes.tokens.plus_plus
|
|
1951
|
-
? IncrementOperator.increment
|
|
1952
|
-
: IncrementOperator.decrement, _var);
|
|
1953
|
-
}
|
|
1954
|
-
_assignment_statement() {
|
|
1955
|
-
// (unary_expression underscore) equal short_circuit_or_expression
|
|
1956
|
-
let _var = null;
|
|
1957
|
-
if (this._check(TokenTypes.tokens.brace_right))
|
|
1958
|
-
return null;
|
|
1959
|
-
let isUnderscore = this._match(TokenTypes.tokens.underscore);
|
|
1960
|
-
if (!isUnderscore)
|
|
1961
|
-
_var = this._unary_expression();
|
|
1962
|
-
if (!isUnderscore && _var == null)
|
|
1963
|
-
return null;
|
|
1964
|
-
const type = this._consume(TokenTypes.assignment_operators, "Expected assignment operator.");
|
|
1965
|
-
const value = this._short_circuit_or_expression();
|
|
1966
|
-
return new Assign(AssignOperator.parse(type.lexeme), _var, value);
|
|
1967
|
-
}
|
|
1968
|
-
_func_call_statement() {
|
|
1969
|
-
// ident argument_expression_list
|
|
1970
|
-
if (!this._check(TokenTypes.tokens.ident))
|
|
1971
|
-
return null;
|
|
1972
|
-
const savedPos = this._current;
|
|
1973
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected function name.");
|
|
1974
|
-
const args = this._argument_expression_list();
|
|
1975
|
-
if (args === null) {
|
|
1976
|
-
this._current = savedPos;
|
|
1977
|
-
return null;
|
|
1978
|
-
}
|
|
1979
|
-
return new Call(name.lexeme, args);
|
|
1980
|
-
}
|
|
1981
|
-
_loop_statement() {
|
|
1982
|
-
// loop brace_left statement* continuing_statement? brace_right
|
|
1983
|
-
if (!this._match(TokenTypes.keywords.loop))
|
|
1984
|
-
return null;
|
|
1985
|
-
this._consume(TokenTypes.tokens.brace_left, "Expected '{' for loop.");
|
|
1986
|
-
// statement*
|
|
1987
|
-
const statements = [];
|
|
1988
|
-
let statement = this._statement();
|
|
1989
|
-
while (statement !== null) {
|
|
1990
|
-
if (Array.isArray(statement)) {
|
|
1991
|
-
for (let s of statement) {
|
|
1992
|
-
statements.push(s);
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
else {
|
|
1996
|
-
statements.push(statement);
|
|
1997
|
-
}
|
|
1998
|
-
statement = this._statement();
|
|
1999
|
-
}
|
|
2000
|
-
// continuing_statement: continuing compound_statement
|
|
2001
|
-
let continuing = null;
|
|
2002
|
-
if (this._match(TokenTypes.keywords.continuing))
|
|
2003
|
-
continuing = this._compound_statement();
|
|
2004
|
-
this._consume(TokenTypes.tokens.brace_right, "Expected '}' for loop.");
|
|
2005
|
-
return new Loop(statements, continuing);
|
|
2006
|
-
}
|
|
2007
|
-
_switch_statement() {
|
|
2008
|
-
// switch optional_paren_expression brace_left switch_body+ brace_right
|
|
2009
|
-
if (!this._match(TokenTypes.keywords.switch))
|
|
2010
|
-
return null;
|
|
2011
|
-
const condition = this._optional_paren_expression();
|
|
2012
|
-
this._consume(TokenTypes.tokens.brace_left, "Expected '{' for switch.");
|
|
2013
|
-
const body = this._switch_body();
|
|
2014
|
-
if (body == null || body.length == 0)
|
|
2015
|
-
throw this._error(this._previous(), "Expected 'case' or 'default'.");
|
|
2016
|
-
this._consume(TokenTypes.tokens.brace_right, "Expected '}' for switch.");
|
|
2017
|
-
return new Switch(condition, body);
|
|
2018
|
-
}
|
|
2019
|
-
_switch_body() {
|
|
2020
|
-
// case case_selectors colon brace_left case_body? brace_right
|
|
2021
|
-
// default colon brace_left case_body? brace_right
|
|
2022
|
-
const cases = [];
|
|
2023
|
-
if (this._match(TokenTypes.keywords.case)) {
|
|
2024
|
-
const selector = this._case_selectors();
|
|
2025
|
-
this._match(TokenTypes.tokens.colon); // colon is optional
|
|
2026
|
-
this._consume(TokenTypes.tokens.brace_left, "Exected '{' for switch case.");
|
|
2027
|
-
const body = this._case_body();
|
|
2028
|
-
this._consume(TokenTypes.tokens.brace_right, "Exected '}' for switch case.");
|
|
2029
|
-
cases.push(new Case(selector, body));
|
|
2030
|
-
}
|
|
2031
|
-
if (this._match(TokenTypes.keywords.default)) {
|
|
2032
|
-
this._match(TokenTypes.tokens.colon); // colon is optional
|
|
2033
|
-
this._consume(TokenTypes.tokens.brace_left, "Exected '{' for switch default.");
|
|
2034
|
-
const body = this._case_body();
|
|
2035
|
-
this._consume(TokenTypes.tokens.brace_right, "Exected '}' for switch default.");
|
|
2036
|
-
cases.push(new Default(body));
|
|
2037
|
-
}
|
|
2038
|
-
if (this._check([TokenTypes.keywords.default, TokenTypes.keywords.case])) {
|
|
2039
|
-
const _cases = this._switch_body();
|
|
2040
|
-
cases.push(_cases[0]);
|
|
2041
|
-
}
|
|
2042
|
-
return cases;
|
|
2043
|
-
}
|
|
2044
|
-
_case_selectors() {
|
|
2045
|
-
var _a, _b, _c, _d;
|
|
2046
|
-
// const_literal (comma const_literal)* comma?
|
|
2047
|
-
const selectors = [
|
|
2048
|
-
(_b = (_a = this._shift_expression()) === null || _a === void 0 ? void 0 : _a.evaluate(this._context).toString()) !== null && _b !== void 0 ? _b : "",
|
|
2049
|
-
];
|
|
2050
|
-
while (this._match(TokenTypes.tokens.comma)) {
|
|
2051
|
-
selectors.push((_d = (_c = this._shift_expression()) === null || _c === void 0 ? void 0 : _c.evaluate(this._context).toString()) !== null && _d !== void 0 ? _d : "");
|
|
2052
|
-
}
|
|
2053
|
-
return selectors;
|
|
2054
|
-
}
|
|
2055
|
-
_case_body() {
|
|
2056
|
-
// statement case_body?
|
|
2057
|
-
// fallthrough semicolon
|
|
2058
|
-
if (this._match(TokenTypes.keywords.fallthrough)) {
|
|
2059
|
-
this._consume(TokenTypes.tokens.semicolon, "Expected ';'");
|
|
2060
|
-
return [];
|
|
2061
|
-
}
|
|
2062
|
-
let statement = this._statement();
|
|
2063
|
-
if (statement == null)
|
|
2064
|
-
return [];
|
|
2065
|
-
if (!(statement instanceof Array)) {
|
|
2066
|
-
statement = [statement];
|
|
2067
|
-
}
|
|
2068
|
-
const nextStatement = this._case_body();
|
|
2069
|
-
if (nextStatement.length == 0)
|
|
2070
|
-
return statement;
|
|
2071
|
-
return [...statement, nextStatement[0]];
|
|
2072
|
-
}
|
|
2073
|
-
_if_statement() {
|
|
2074
|
-
// if optional_paren_expression compound_statement elseif_statement? else_statement?
|
|
2075
|
-
if (!this._match(TokenTypes.keywords.if))
|
|
2076
|
-
return null;
|
|
2077
|
-
const condition = this._optional_paren_expression();
|
|
2078
|
-
const block = this._compound_statement();
|
|
2079
|
-
let elseif = [];
|
|
2080
|
-
if (this._match_elseif()) {
|
|
2081
|
-
elseif = this._elseif_statement(elseif);
|
|
2082
|
-
}
|
|
2083
|
-
let _else = null;
|
|
2084
|
-
if (this._match(TokenTypes.keywords.else))
|
|
2085
|
-
_else = this._compound_statement();
|
|
2086
|
-
return new If(condition, block, elseif, _else);
|
|
2087
|
-
}
|
|
2088
|
-
_match_elseif() {
|
|
2089
|
-
if (this._tokens[this._current].type === TokenTypes.keywords.else &&
|
|
2090
|
-
this._tokens[this._current + 1].type === TokenTypes.keywords.if) {
|
|
2091
|
-
this._advance();
|
|
2092
|
-
this._advance();
|
|
2093
|
-
return true;
|
|
2094
|
-
}
|
|
2095
|
-
return false;
|
|
2096
|
-
}
|
|
2097
|
-
_elseif_statement(elseif = []) {
|
|
2098
|
-
// else_if optional_paren_expression compound_statement elseif_statement?
|
|
2099
|
-
const condition = this._optional_paren_expression();
|
|
2100
|
-
const block = this._compound_statement();
|
|
2101
|
-
elseif.push(new ElseIf(condition, block));
|
|
2102
|
-
if (this._match_elseif()) {
|
|
2103
|
-
this._elseif_statement(elseif);
|
|
2104
|
-
}
|
|
2105
|
-
return elseif;
|
|
2106
|
-
}
|
|
2107
|
-
_return_statement() {
|
|
2108
|
-
// return short_circuit_or_expression?
|
|
2109
|
-
if (!this._match(TokenTypes.keywords.return))
|
|
2110
|
-
return null;
|
|
2111
|
-
const value = this._short_circuit_or_expression();
|
|
2112
|
-
return new Return(value);
|
|
2113
|
-
}
|
|
2114
|
-
_short_circuit_or_expression() {
|
|
2115
|
-
// short_circuit_and_expression
|
|
2116
|
-
// short_circuit_or_expression or_or short_circuit_and_expression
|
|
2117
|
-
let expr = this._short_circuit_and_expr();
|
|
2118
|
-
while (this._match(TokenTypes.tokens.or_or)) {
|
|
2119
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._short_circuit_and_expr());
|
|
2120
|
-
}
|
|
2121
|
-
return expr;
|
|
2122
|
-
}
|
|
2123
|
-
_short_circuit_and_expr() {
|
|
2124
|
-
// inclusive_or_expression
|
|
2125
|
-
// short_circuit_and_expression and_and inclusive_or_expression
|
|
2126
|
-
let expr = this._inclusive_or_expression();
|
|
2127
|
-
while (this._match(TokenTypes.tokens.and_and)) {
|
|
2128
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._inclusive_or_expression());
|
|
2129
|
-
}
|
|
2130
|
-
return expr;
|
|
2131
|
-
}
|
|
2132
|
-
_inclusive_or_expression() {
|
|
2133
|
-
// exclusive_or_expression
|
|
2134
|
-
// inclusive_or_expression or exclusive_or_expression
|
|
2135
|
-
let expr = this._exclusive_or_expression();
|
|
2136
|
-
while (this._match(TokenTypes.tokens.or)) {
|
|
2137
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._exclusive_or_expression());
|
|
2138
|
-
}
|
|
2139
|
-
return expr;
|
|
2140
|
-
}
|
|
2141
|
-
_exclusive_or_expression() {
|
|
2142
|
-
// and_expression
|
|
2143
|
-
// exclusive_or_expression xor and_expression
|
|
2144
|
-
let expr = this._and_expression();
|
|
2145
|
-
while (this._match(TokenTypes.tokens.xor)) {
|
|
2146
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._and_expression());
|
|
2147
|
-
}
|
|
2148
|
-
return expr;
|
|
2149
|
-
}
|
|
2150
|
-
_and_expression() {
|
|
2151
|
-
// equality_expression
|
|
2152
|
-
// and_expression and equality_expression
|
|
2153
|
-
let expr = this._equality_expression();
|
|
2154
|
-
while (this._match(TokenTypes.tokens.and)) {
|
|
2155
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._equality_expression());
|
|
2156
|
-
}
|
|
2157
|
-
return expr;
|
|
2158
|
-
}
|
|
2159
|
-
_equality_expression() {
|
|
2160
|
-
// relational_expression
|
|
2161
|
-
// relational_expression equal_equal relational_expression
|
|
2162
|
-
// relational_expression not_equal relational_expression
|
|
2163
|
-
const expr = this._relational_expression();
|
|
2164
|
-
if (this._match([TokenTypes.tokens.equal_equal, TokenTypes.tokens.not_equal])) {
|
|
2165
|
-
return new BinaryOperator(this._previous().toString(), expr, this._relational_expression());
|
|
2166
|
-
}
|
|
2167
|
-
return expr;
|
|
2168
|
-
}
|
|
2169
|
-
_relational_expression() {
|
|
2170
|
-
// shift_expression
|
|
2171
|
-
// relational_expression less_than shift_expression
|
|
2172
|
-
// relational_expression greater_than shift_expression
|
|
2173
|
-
// relational_expression less_than_equal shift_expression
|
|
2174
|
-
// relational_expression greater_than_equal shift_expression
|
|
2175
|
-
let expr = this._shift_expression();
|
|
2176
|
-
while (this._match([
|
|
2177
|
-
TokenTypes.tokens.less_than,
|
|
2178
|
-
TokenTypes.tokens.greater_than,
|
|
2179
|
-
TokenTypes.tokens.less_than_equal,
|
|
2180
|
-
TokenTypes.tokens.greater_than_equal,
|
|
2181
|
-
])) {
|
|
2182
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._shift_expression());
|
|
2183
|
-
}
|
|
2184
|
-
return expr;
|
|
2185
|
-
}
|
|
2186
|
-
_shift_expression() {
|
|
2187
|
-
// additive_expression
|
|
2188
|
-
// shift_expression shift_left additive_expression
|
|
2189
|
-
// shift_expression shift_right additive_expression
|
|
2190
|
-
let expr = this._additive_expression();
|
|
2191
|
-
while (this._match([TokenTypes.tokens.shift_left, TokenTypes.tokens.shift_right])) {
|
|
2192
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._additive_expression());
|
|
2193
|
-
}
|
|
2194
|
-
return expr;
|
|
2195
|
-
}
|
|
2196
|
-
_additive_expression() {
|
|
2197
|
-
// multiplicative_expression
|
|
2198
|
-
// additive_expression plus multiplicative_expression
|
|
2199
|
-
// additive_expression minus multiplicative_expression
|
|
2200
|
-
let expr = this._multiplicative_expression();
|
|
2201
|
-
while (this._match([TokenTypes.tokens.plus, TokenTypes.tokens.minus])) {
|
|
2202
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._multiplicative_expression());
|
|
2203
|
-
}
|
|
2204
|
-
return expr;
|
|
2205
|
-
}
|
|
2206
|
-
_multiplicative_expression() {
|
|
2207
|
-
// unary_expression
|
|
2208
|
-
// multiplicative_expression star unary_expression
|
|
2209
|
-
// multiplicative_expression forward_slash unary_expression
|
|
2210
|
-
// multiplicative_expression modulo unary_expression
|
|
2211
|
-
let expr = this._unary_expression();
|
|
2212
|
-
while (this._match([
|
|
2213
|
-
TokenTypes.tokens.star,
|
|
2214
|
-
TokenTypes.tokens.forward_slash,
|
|
2215
|
-
TokenTypes.tokens.modulo,
|
|
2216
|
-
])) {
|
|
2217
|
-
expr = new BinaryOperator(this._previous().toString(), expr, this._unary_expression());
|
|
2218
|
-
}
|
|
2219
|
-
return expr;
|
|
2220
|
-
}
|
|
2221
|
-
_unary_expression() {
|
|
2222
|
-
// singular_expression
|
|
2223
|
-
// minus unary_expression
|
|
2224
|
-
// bang unary_expression
|
|
2225
|
-
// tilde unary_expression
|
|
2226
|
-
// star unary_expression
|
|
2227
|
-
// and unary_expression
|
|
2228
|
-
if (this._match([
|
|
2229
|
-
TokenTypes.tokens.minus,
|
|
2230
|
-
TokenTypes.tokens.bang,
|
|
2231
|
-
TokenTypes.tokens.tilde,
|
|
2232
|
-
TokenTypes.tokens.star,
|
|
2233
|
-
TokenTypes.tokens.and,
|
|
2234
|
-
])) {
|
|
2235
|
-
return new UnaryOperator(this._previous().toString(), this._unary_expression());
|
|
2236
|
-
}
|
|
2237
|
-
return this._singular_expression();
|
|
2238
|
-
}
|
|
2239
|
-
_singular_expression() {
|
|
2240
|
-
// primary_expression postfix_expression ?
|
|
2241
|
-
const expr = this._primary_expression();
|
|
2242
|
-
const p = this._postfix_expression();
|
|
2243
|
-
if (p)
|
|
2244
|
-
expr.postfix = p;
|
|
2245
|
-
return expr;
|
|
2246
|
-
}
|
|
2247
|
-
_postfix_expression() {
|
|
2248
|
-
// bracket_left short_circuit_or_expression bracket_right postfix_expression?
|
|
2249
|
-
if (this._match(TokenTypes.tokens.bracket_left)) {
|
|
2250
|
-
const expr = this._short_circuit_or_expression();
|
|
2251
|
-
this._consume(TokenTypes.tokens.bracket_right, "Expected ']'.");
|
|
2252
|
-
const p = this._postfix_expression();
|
|
2253
|
-
if (p)
|
|
2254
|
-
expr.postfix = p;
|
|
2255
|
-
return expr;
|
|
2256
|
-
}
|
|
2257
|
-
// period ident postfix_expression?
|
|
2258
|
-
if (this._match(TokenTypes.tokens.period)) {
|
|
2259
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected member name.");
|
|
2260
|
-
const p = this._postfix_expression();
|
|
2261
|
-
const expr = new StringExpr(name.lexeme);
|
|
2262
|
-
if (p)
|
|
2263
|
-
expr.postfix = p;
|
|
2264
|
-
return expr;
|
|
2265
|
-
}
|
|
2266
|
-
return null;
|
|
2267
|
-
}
|
|
2268
|
-
_getStruct(name) {
|
|
2269
|
-
if (this._context.aliases.has(name)) {
|
|
2270
|
-
const alias = this._context.aliases.get(name).type;
|
|
2271
|
-
return alias;
|
|
2272
|
-
}
|
|
2273
|
-
if (this._context.structs.has(name)) {
|
|
2274
|
-
const struct = this._context.structs.get(name);
|
|
2275
|
-
return struct;
|
|
2276
|
-
}
|
|
2277
|
-
return null;
|
|
2278
|
-
}
|
|
2279
|
-
_primary_expression() {
|
|
2280
|
-
// ident argument_expression_list?
|
|
2281
|
-
if (this._match(TokenTypes.tokens.ident)) {
|
|
2282
|
-
const name = this._previous().toString();
|
|
2283
|
-
if (this._check(TokenTypes.tokens.paren_left)) {
|
|
2284
|
-
const args = this._argument_expression_list();
|
|
2285
|
-
const struct = this._getStruct(name);
|
|
2286
|
-
if (struct != null) {
|
|
2287
|
-
return new CreateExpr(struct, args);
|
|
2288
|
-
}
|
|
2289
|
-
return new CallExpr(name, args);
|
|
2290
|
-
}
|
|
2291
|
-
if (this._context.constants.has(name)) {
|
|
2292
|
-
const c = this._context.constants.get(name);
|
|
2293
|
-
return new ConstExpr(name, c.value);
|
|
2294
|
-
}
|
|
2295
|
-
return new VariableExpr(name);
|
|
2296
|
-
}
|
|
2297
|
-
// const_literal
|
|
2298
|
-
if (this._match(TokenTypes.const_literal)) {
|
|
2299
|
-
return new LiteralExpr(parseFloat(this._previous().toString()));
|
|
2300
|
-
}
|
|
2301
|
-
// paren_expression
|
|
2302
|
-
if (this._check(TokenTypes.tokens.paren_left)) {
|
|
2303
|
-
return this._paren_expression();
|
|
2304
|
-
}
|
|
2305
|
-
// bitcast less_than type_decl greater_than paren_expression
|
|
2306
|
-
if (this._match(TokenTypes.keywords.bitcast)) {
|
|
2307
|
-
this._consume(TokenTypes.tokens.less_than, "Expected '<'.");
|
|
2308
|
-
const type = this._type_decl();
|
|
2309
|
-
this._consume(TokenTypes.tokens.greater_than, "Expected '>'.");
|
|
2310
|
-
const value = this._paren_expression();
|
|
2311
|
-
return new BitcastExpr(type, value);
|
|
2312
|
-
}
|
|
2313
|
-
// type_decl argument_expression_list
|
|
2314
|
-
const type = this._type_decl();
|
|
2315
|
-
const args = this._argument_expression_list();
|
|
2316
|
-
return new TypecastExpr(type, args);
|
|
2317
|
-
}
|
|
2318
|
-
_argument_expression_list() {
|
|
2319
|
-
// paren_left ((short_circuit_or_expression comma)* short_circuit_or_expression comma?)? paren_right
|
|
2320
|
-
if (!this._match(TokenTypes.tokens.paren_left))
|
|
2321
|
-
return null;
|
|
2322
|
-
const args = [];
|
|
2323
|
-
do {
|
|
2324
|
-
if (this._check(TokenTypes.tokens.paren_right))
|
|
2325
|
-
break;
|
|
2326
|
-
const arg = this._short_circuit_or_expression();
|
|
2327
|
-
args.push(arg);
|
|
2328
|
-
} while (this._match(TokenTypes.tokens.comma));
|
|
2329
|
-
this._consume(TokenTypes.tokens.paren_right, "Expected ')' for agument list");
|
|
2330
|
-
return args;
|
|
2331
|
-
}
|
|
2332
|
-
_optional_paren_expression() {
|
|
2333
|
-
// [paren_left] short_circuit_or_expression [paren_right]
|
|
2334
|
-
this._match(TokenTypes.tokens.paren_left);
|
|
2335
|
-
const expr = this._short_circuit_or_expression();
|
|
2336
|
-
this._match(TokenTypes.tokens.paren_right);
|
|
2337
|
-
return new GroupingExpr([expr]);
|
|
2338
|
-
}
|
|
2339
|
-
_paren_expression() {
|
|
2340
|
-
// paren_left short_circuit_or_expression paren_right
|
|
2341
|
-
this._consume(TokenTypes.tokens.paren_left, "Expected '('.");
|
|
2342
|
-
const expr = this._short_circuit_or_expression();
|
|
2343
|
-
this._consume(TokenTypes.tokens.paren_right, "Expected ')'.");
|
|
2344
|
-
return new GroupingExpr([expr]);
|
|
2345
|
-
}
|
|
2346
|
-
_struct_decl() {
|
|
2347
|
-
// attribute* struct ident struct_body_decl
|
|
2348
|
-
if (!this._match(TokenTypes.keywords.struct))
|
|
2349
|
-
return null;
|
|
2350
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected name for struct.").toString();
|
|
2351
|
-
// struct_body_decl: brace_left (struct_member comma)* struct_member comma? brace_right
|
|
2352
|
-
this._consume(TokenTypes.tokens.brace_left, "Expected '{' for struct body.");
|
|
2353
|
-
const members = [];
|
|
2354
|
-
while (!this._check(TokenTypes.tokens.brace_right)) {
|
|
2355
|
-
// struct_member: attribute* variable_ident_decl
|
|
2356
|
-
const memberAttrs = this._attribute();
|
|
2357
|
-
const memberName = this._consume(TokenTypes.tokens.ident, "Expected variable name.").toString();
|
|
2358
|
-
this._consume(TokenTypes.tokens.colon, "Expected ':' for struct member type.");
|
|
2359
|
-
const typeAttrs = this._attribute();
|
|
2360
|
-
const memberType = this._type_decl();
|
|
2361
|
-
if (memberType != null)
|
|
2362
|
-
memberType.attributes = typeAttrs;
|
|
2363
|
-
if (!this._check(TokenTypes.tokens.brace_right))
|
|
2364
|
-
this._consume(TokenTypes.tokens.comma, "Expected ',' for struct member.");
|
|
2365
|
-
else
|
|
2366
|
-
this._match(TokenTypes.tokens.comma); // trailing comma optional.
|
|
2367
|
-
members.push(new Member(memberName, memberType, memberAttrs));
|
|
2368
|
-
}
|
|
2369
|
-
this._consume(TokenTypes.tokens.brace_right, "Expected '}' after struct body.");
|
|
2370
|
-
const structNode = new Struct(name, members);
|
|
2371
|
-
this._context.structs.set(name, structNode);
|
|
2372
|
-
return structNode;
|
|
2373
|
-
}
|
|
2374
|
-
_global_variable_decl() {
|
|
2375
|
-
// attribute* variable_decl (equal const_expression)?
|
|
2376
|
-
const _var = this._variable_decl();
|
|
2377
|
-
if (_var && this._match(TokenTypes.tokens.equal))
|
|
2378
|
-
_var.value = this._const_expression();
|
|
2379
|
-
return _var;
|
|
2380
|
-
}
|
|
2381
|
-
_override_variable_decl() {
|
|
2382
|
-
// attribute* override_decl (equal const_expression)?
|
|
2383
|
-
const _override = this._override_decl();
|
|
2384
|
-
if (_override && this._match(TokenTypes.tokens.equal))
|
|
2385
|
-
_override.value = this._const_expression();
|
|
2386
|
-
return _override;
|
|
2387
|
-
}
|
|
2388
|
-
_global_const_decl() {
|
|
2389
|
-
// attribute* const (ident variable_ident_decl) global_const_initializer?
|
|
2390
|
-
if (!this._match(TokenTypes.keywords.const))
|
|
2391
|
-
return null;
|
|
2392
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected variable name");
|
|
2393
|
-
let type = null;
|
|
2394
|
-
if (this._match(TokenTypes.tokens.colon)) {
|
|
2395
|
-
const attrs = this._attribute();
|
|
2396
|
-
type = this._type_decl();
|
|
2397
|
-
if (type != null)
|
|
2398
|
-
type.attributes = attrs;
|
|
2399
|
-
}
|
|
2400
|
-
let value = null;
|
|
2401
|
-
if (this._match(TokenTypes.tokens.equal)) {
|
|
2402
|
-
const valueExpr = this._short_circuit_or_expression();
|
|
2403
|
-
if (valueExpr instanceof CreateExpr) {
|
|
2404
|
-
value = valueExpr;
|
|
2405
|
-
}
|
|
2406
|
-
else if (valueExpr instanceof ConstExpr &&
|
|
2407
|
-
valueExpr.initializer instanceof CreateExpr) {
|
|
2408
|
-
value = valueExpr.initializer;
|
|
2409
|
-
}
|
|
2410
|
-
else {
|
|
2411
|
-
try {
|
|
2412
|
-
const constValue = valueExpr.evaluate(this._context);
|
|
2413
|
-
value = new LiteralExpr(constValue);
|
|
2414
|
-
}
|
|
2415
|
-
catch (_a) {
|
|
2416
|
-
value = valueExpr;
|
|
2417
|
-
}
|
|
2418
|
-
}
|
|
2419
|
-
}
|
|
2420
|
-
const c = new Const(name.toString(), type, "", "", value);
|
|
2421
|
-
this._context.constants.set(c.name, c);
|
|
2422
|
-
return c;
|
|
2423
|
-
}
|
|
2424
|
-
_global_let_decl() {
|
|
2425
|
-
// attribute* let (ident variable_ident_decl) global_const_initializer?
|
|
2426
|
-
if (!this._match(TokenTypes.keywords.let))
|
|
2427
|
-
return null;
|
|
2428
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected variable name");
|
|
2429
|
-
let type = null;
|
|
2430
|
-
if (this._match(TokenTypes.tokens.colon)) {
|
|
2431
|
-
const attrs = this._attribute();
|
|
2432
|
-
type = this._type_decl();
|
|
2433
|
-
if (type != null)
|
|
2434
|
-
type.attributes = attrs;
|
|
2435
|
-
}
|
|
2436
|
-
let value = null;
|
|
2437
|
-
if (this._match(TokenTypes.tokens.equal)) {
|
|
2438
|
-
value = this._const_expression();
|
|
2439
|
-
}
|
|
2440
|
-
return new Let(name.toString(), type, "", "", value);
|
|
2441
|
-
}
|
|
2442
|
-
_const_expression() {
|
|
2443
|
-
// type_decl paren_left ((const_expression comma)* const_expression comma?)? paren_right
|
|
2444
|
-
// const_literal
|
|
2445
|
-
if (this._match(TokenTypes.const_literal))
|
|
2446
|
-
return new StringExpr(this._previous().toString());
|
|
2447
|
-
const type = this._type_decl();
|
|
2448
|
-
this._consume(TokenTypes.tokens.paren_left, "Expected '('.");
|
|
2449
|
-
let args = [];
|
|
2450
|
-
while (!this._check(TokenTypes.tokens.paren_right)) {
|
|
2451
|
-
args.push(this._const_expression());
|
|
2452
|
-
if (!this._check(TokenTypes.tokens.comma))
|
|
2453
|
-
break;
|
|
2454
|
-
this._advance();
|
|
2455
|
-
}
|
|
2456
|
-
this._consume(TokenTypes.tokens.paren_right, "Expected ')'.");
|
|
2457
|
-
return new CreateExpr(type, args);
|
|
2458
|
-
}
|
|
2459
|
-
_variable_decl() {
|
|
2460
|
-
// var variable_qualifier? (ident variable_ident_decl)
|
|
2461
|
-
if (!this._match(TokenTypes.keywords.var))
|
|
2462
|
-
return null;
|
|
2463
|
-
// variable_qualifier: less_than storage_class (comma access_mode)? greater_than
|
|
2464
|
-
let storage = "";
|
|
2465
|
-
let access = "";
|
|
2466
|
-
if (this._match(TokenTypes.tokens.less_than)) {
|
|
2467
|
-
storage = this._consume(TokenTypes.storage_class, "Expected storage_class.").toString();
|
|
2468
|
-
if (this._match(TokenTypes.tokens.comma))
|
|
2469
|
-
access = this._consume(TokenTypes.access_mode, "Expected access_mode.").toString();
|
|
2470
|
-
this._consume(TokenTypes.tokens.greater_than, "Expected '>'.");
|
|
2471
|
-
}
|
|
2472
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected variable name");
|
|
2473
|
-
let type = null;
|
|
2474
|
-
if (this._match(TokenTypes.tokens.colon)) {
|
|
2475
|
-
const attrs = this._attribute();
|
|
2476
|
-
type = this._type_decl();
|
|
2477
|
-
if (type != null)
|
|
2478
|
-
type.attributes = attrs;
|
|
2479
|
-
}
|
|
2480
|
-
return new Var(name.toString(), type, storage, access, null);
|
|
2481
|
-
}
|
|
2482
|
-
_override_decl() {
|
|
2483
|
-
// override (ident variable_ident_decl)
|
|
2484
|
-
if (!this._match(TokenTypes.keywords.override))
|
|
2485
|
-
return null;
|
|
2486
|
-
const name = this._consume(TokenTypes.tokens.ident, "Expected variable name");
|
|
2487
|
-
let type = null;
|
|
2488
|
-
if (this._match(TokenTypes.tokens.colon)) {
|
|
2489
|
-
const attrs = this._attribute();
|
|
2490
|
-
type = this._type_decl();
|
|
2491
|
-
if (type != null)
|
|
2492
|
-
type.attributes = attrs;
|
|
2493
|
-
}
|
|
2494
|
-
return new Override(name.toString(), type, null);
|
|
2495
|
-
}
|
|
2496
|
-
_enable_directive() {
|
|
2497
|
-
// enable ident semicolon
|
|
2498
|
-
const name = this._consume(TokenTypes.tokens.ident, "identity expected.");
|
|
2499
|
-
return new Enable(name.toString());
|
|
2500
|
-
}
|
|
2501
|
-
_type_alias() {
|
|
2502
|
-
// type ident equal type_decl
|
|
2503
|
-
const name = this._consume(TokenTypes.tokens.ident, "identity expected.");
|
|
2504
|
-
this._consume(TokenTypes.tokens.equal, "Expected '=' for type alias.");
|
|
2505
|
-
let aliasType = this._type_decl();
|
|
2506
|
-
if (aliasType === null) {
|
|
2507
|
-
throw this._error(this._peek(), "Expected Type for Alias.");
|
|
2508
|
-
}
|
|
2509
|
-
if (this._context.aliases.has(aliasType.name)) {
|
|
2510
|
-
aliasType = this._context.aliases.get(aliasType.name).type;
|
|
2511
|
-
}
|
|
2512
|
-
const aliasNode = new Alias(name.toString(), aliasType);
|
|
2513
|
-
this._context.aliases.set(aliasNode.name, aliasNode);
|
|
2514
|
-
return aliasNode;
|
|
2515
|
-
}
|
|
2516
|
-
_type_decl() {
|
|
2517
|
-
// ident
|
|
2518
|
-
// bool
|
|
2519
|
-
// float32
|
|
2520
|
-
// int32
|
|
2521
|
-
// uint32
|
|
2522
|
-
// vec2 less_than type_decl greater_than
|
|
2523
|
-
// vec3 less_than type_decl greater_than
|
|
2524
|
-
// vec4 less_than type_decl greater_than
|
|
2525
|
-
// mat2x2 less_than type_decl greater_than
|
|
2526
|
-
// mat2x3 less_than type_decl greater_than
|
|
2527
|
-
// mat2x4 less_than type_decl greater_than
|
|
2528
|
-
// mat3x2 less_than type_decl greater_than
|
|
2529
|
-
// mat3x3 less_than type_decl greater_than
|
|
2530
|
-
// mat3x4 less_than type_decl greater_than
|
|
2531
|
-
// mat4x2 less_than type_decl greater_than
|
|
2532
|
-
// mat4x3 less_than type_decl greater_than
|
|
2533
|
-
// mat4x4 less_than type_decl greater_than
|
|
2534
|
-
// atomic less_than type_decl greater_than
|
|
2535
|
-
// pointer less_than storage_class comma type_decl (comma access_mode)? greater_than
|
|
2536
|
-
// array_type_decl
|
|
2537
|
-
// texture_sampler_types
|
|
2538
|
-
if (this._check([
|
|
2539
|
-
TokenTypes.tokens.ident,
|
|
2540
|
-
...TokenTypes.texel_format,
|
|
2541
|
-
TokenTypes.keywords.bool,
|
|
2542
|
-
TokenTypes.keywords.f32,
|
|
2543
|
-
TokenTypes.keywords.i32,
|
|
2544
|
-
TokenTypes.keywords.u32,
|
|
2545
|
-
])) {
|
|
2546
|
-
const type = this._advance();
|
|
2547
|
-
const typeName = type.toString();
|
|
2548
|
-
if (this._context.structs.has(typeName)) {
|
|
2549
|
-
return this._context.structs.get(typeName);
|
|
2550
|
-
}
|
|
2551
|
-
if (this._context.aliases.has(typeName)) {
|
|
2552
|
-
return this._context.aliases.get(typeName).type;
|
|
2553
|
-
}
|
|
2554
|
-
return new Type(type.toString());
|
|
2555
|
-
}
|
|
2556
|
-
// texture_sampler_types
|
|
2557
|
-
let type = this._texture_sampler_types();
|
|
2558
|
-
if (type)
|
|
2559
|
-
return type;
|
|
2560
|
-
if (this._check(TokenTypes.template_types)) {
|
|
2561
|
-
let type = this._advance().toString();
|
|
2562
|
-
let format = null;
|
|
2563
|
-
let access = null;
|
|
2564
|
-
if (this._match(TokenTypes.tokens.less_than)) {
|
|
2565
|
-
format = this._type_decl();
|
|
2566
|
-
access = null;
|
|
2567
|
-
if (this._match(TokenTypes.tokens.comma))
|
|
2568
|
-
access = this._consume(TokenTypes.access_mode, "Expected access_mode for pointer").toString();
|
|
2569
|
-
this._consume(TokenTypes.tokens.greater_than, "Expected '>' for type.");
|
|
2570
|
-
}
|
|
2571
|
-
return new TemplateType(type, format, access);
|
|
2572
|
-
}
|
|
2573
|
-
// pointer less_than storage_class comma type_decl (comma access_mode)? greater_than
|
|
2574
|
-
if (this._match(TokenTypes.keywords.ptr)) {
|
|
2575
|
-
let pointer = this._previous().toString();
|
|
2576
|
-
this._consume(TokenTypes.tokens.less_than, "Expected '<' for pointer.");
|
|
2577
|
-
const storage = this._consume(TokenTypes.storage_class, "Expected storage_class for pointer");
|
|
2578
|
-
this._consume(TokenTypes.tokens.comma, "Expected ',' for pointer.");
|
|
2579
|
-
const decl = this._type_decl();
|
|
2580
|
-
let access = null;
|
|
2581
|
-
if (this._match(TokenTypes.tokens.comma))
|
|
2582
|
-
access = this._consume(TokenTypes.access_mode, "Expected access_mode for pointer").toString();
|
|
2583
|
-
this._consume(TokenTypes.tokens.greater_than, "Expected '>' for pointer.");
|
|
2584
|
-
return new PointerType(pointer, storage.toString(), decl, access);
|
|
2585
|
-
}
|
|
2586
|
-
// The following type_decl's have an optional attribyte_list*
|
|
2587
|
-
const attrs = this._attribute();
|
|
2588
|
-
// attribute* array
|
|
2589
|
-
// attribute* array less_than type_decl (comma element_count_expression)? greater_than
|
|
2590
|
-
if (this._match(TokenTypes.keywords.array)) {
|
|
2591
|
-
let format = null;
|
|
2592
|
-
let countInt = -1;
|
|
2593
|
-
const array = this._previous();
|
|
2594
|
-
if (this._match(TokenTypes.tokens.less_than)) {
|
|
2595
|
-
format = this._type_decl();
|
|
2596
|
-
if (this._context.aliases.has(format.name)) {
|
|
2597
|
-
format = this._context.aliases.get(format.name).type;
|
|
2598
|
-
}
|
|
2599
|
-
let count = "";
|
|
2600
|
-
if (this._match(TokenTypes.tokens.comma)) {
|
|
2601
|
-
let c = this._shift_expression();
|
|
2602
|
-
count = c.evaluate(this._context).toString();
|
|
2603
|
-
}
|
|
2604
|
-
this._consume(TokenTypes.tokens.greater_than, "Expected '>' for array.");
|
|
2605
|
-
countInt = count ? parseInt(count) : 0;
|
|
2606
|
-
}
|
|
2607
|
-
return new ArrayType(array.toString(), attrs, format, countInt);
|
|
2608
|
-
}
|
|
2609
|
-
return null;
|
|
2610
|
-
}
|
|
2611
|
-
_texture_sampler_types() {
|
|
2612
|
-
// sampler_type
|
|
2613
|
-
if (this._match(TokenTypes.sampler_type))
|
|
2614
|
-
return new SamplerType(this._previous().toString(), null, null);
|
|
2615
|
-
// depth_texture_type
|
|
2616
|
-
if (this._match(TokenTypes.depth_texture_type))
|
|
2617
|
-
return new SamplerType(this._previous().toString(), null, null);
|
|
2618
|
-
// sampled_texture_type less_than type_decl greater_than
|
|
2619
|
-
// multisampled_texture_type less_than type_decl greater_than
|
|
2620
|
-
if (this._match(TokenTypes.sampled_texture_type) ||
|
|
2621
|
-
this._match(TokenTypes.multisampled_texture_type)) {
|
|
2622
|
-
const sampler = this._previous();
|
|
2623
|
-
this._consume(TokenTypes.tokens.less_than, "Expected '<' for sampler type.");
|
|
2624
|
-
const format = this._type_decl();
|
|
2625
|
-
this._consume(TokenTypes.tokens.greater_than, "Expected '>' for sampler type.");
|
|
2626
|
-
return new SamplerType(sampler.toString(), format, null);
|
|
2627
|
-
}
|
|
2628
|
-
// storage_texture_type less_than texel_format comma access_mode greater_than
|
|
2629
|
-
if (this._match(TokenTypes.storage_texture_type)) {
|
|
2630
|
-
const sampler = this._previous();
|
|
2631
|
-
this._consume(TokenTypes.tokens.less_than, "Expected '<' for sampler type.");
|
|
2632
|
-
const format = this._consume(TokenTypes.texel_format, "Invalid texel format.").toString();
|
|
2633
|
-
this._consume(TokenTypes.tokens.comma, "Expected ',' after texel format.");
|
|
2634
|
-
const access = this._consume(TokenTypes.access_mode, "Expected access mode for storage texture type.").toString();
|
|
2635
|
-
this._consume(TokenTypes.tokens.greater_than, "Expected '>' for sampler type.");
|
|
2636
|
-
return new SamplerType(sampler.toString(), format, access);
|
|
2637
|
-
}
|
|
2638
|
-
return null;
|
|
2639
|
-
}
|
|
2640
|
-
_attribute() {
|
|
2641
|
-
// attr ident paren_left (literal_or_ident comma)* literal_or_ident paren_right
|
|
2642
|
-
// attr ident
|
|
2643
|
-
let attributes = [];
|
|
2644
|
-
while (this._match(TokenTypes.tokens.attr)) {
|
|
2645
|
-
const name = this._consume(TokenTypes.attribute_name, "Expected attribute name");
|
|
2646
|
-
const attr = new Attribute(name.toString(), null);
|
|
2647
|
-
if (this._match(TokenTypes.tokens.paren_left)) {
|
|
2648
|
-
// literal_or_ident
|
|
2649
|
-
attr.value = this._consume(TokenTypes.literal_or_ident, "Expected attribute value").toString();
|
|
2650
|
-
if (this._check(TokenTypes.tokens.comma)) {
|
|
2651
|
-
this._advance();
|
|
2652
|
-
do {
|
|
2653
|
-
const v = this._consume(TokenTypes.literal_or_ident, "Expected attribute value").toString();
|
|
2654
|
-
if (!(attr.value instanceof Array)) {
|
|
2655
|
-
attr.value = [attr.value];
|
|
2656
|
-
}
|
|
2657
|
-
attr.value.push(v);
|
|
2658
|
-
} while (this._match(TokenTypes.tokens.comma));
|
|
2659
|
-
}
|
|
2660
|
-
this._consume(TokenTypes.tokens.paren_right, "Expected ')'");
|
|
2661
|
-
}
|
|
2662
|
-
attributes.push(attr);
|
|
2663
|
-
}
|
|
2664
|
-
// Deprecated:
|
|
2665
|
-
// attr_left (attribute comma)* attribute attr_right
|
|
2666
|
-
while (this._match(TokenTypes.tokens.attr_left)) {
|
|
2667
|
-
if (!this._check(TokenTypes.tokens.attr_right)) {
|
|
2668
|
-
do {
|
|
2669
|
-
const name = this._consume(TokenTypes.attribute_name, "Expected attribute name");
|
|
2670
|
-
const attr = new Attribute(name.toString(), null);
|
|
2671
|
-
if (this._match(TokenTypes.tokens.paren_left)) {
|
|
2672
|
-
// literal_or_ident
|
|
2673
|
-
attr.value = [
|
|
2674
|
-
this._consume(TokenTypes.literal_or_ident, "Expected attribute value").toString(),
|
|
2675
|
-
];
|
|
2676
|
-
if (this._check(TokenTypes.tokens.comma)) {
|
|
2677
|
-
this._advance();
|
|
2678
|
-
do {
|
|
2679
|
-
const v = this._consume(TokenTypes.literal_or_ident, "Expected attribute value").toString();
|
|
2680
|
-
attr.value.push(v);
|
|
2681
|
-
} while (this._match(TokenTypes.tokens.comma));
|
|
2682
|
-
}
|
|
2683
|
-
this._consume(TokenTypes.tokens.paren_right, "Expected ')'");
|
|
2684
|
-
}
|
|
2685
|
-
attributes.push(attr);
|
|
2686
|
-
} while (this._match(TokenTypes.tokens.comma));
|
|
2687
|
-
}
|
|
2688
|
-
// Consume ]]
|
|
2689
|
-
this._consume(TokenTypes.tokens.attr_right, "Expected ']]' after attribute declarations");
|
|
2690
|
-
}
|
|
2691
|
-
if (attributes.length == 0)
|
|
2692
|
-
return null;
|
|
2693
|
-
return attributes;
|
|
2694
|
-
}
|
|
2695
|
-
}
|
|
2696
|
-
/**
|
|
2697
|
-
* @author Brendan Duncan / https://github.com/brendan-duncan
|
|
2698
|
-
*/
|
|
2699
|
-
class TypeInfo {
|
|
2700
|
-
constructor(name, attributes) {
|
|
2701
|
-
this.name = name;
|
|
2702
|
-
this.attributes = attributes;
|
|
2703
|
-
this.size = 0;
|
|
2704
|
-
}
|
|
2705
|
-
get isArray() {
|
|
2706
|
-
return false;
|
|
2707
|
-
}
|
|
2708
|
-
get isStruct() {
|
|
2709
|
-
return false;
|
|
2710
|
-
}
|
|
2711
|
-
get isTemplate() {
|
|
2712
|
-
return false;
|
|
2713
|
-
}
|
|
2714
|
-
}
|
|
2715
|
-
class MemberInfo {
|
|
2716
|
-
constructor(name, type, attributes) {
|
|
2717
|
-
this.name = name;
|
|
2718
|
-
this.type = type;
|
|
2719
|
-
this.attributes = attributes;
|
|
2720
|
-
this.offset = 0;
|
|
2721
|
-
this.size = 0;
|
|
2722
|
-
}
|
|
2723
|
-
get isArray() {
|
|
2724
|
-
return this.type.isArray;
|
|
2725
|
-
}
|
|
2726
|
-
get isStruct() {
|
|
2727
|
-
return this.type.isStruct;
|
|
2728
|
-
}
|
|
2729
|
-
get isTemplate() {
|
|
2730
|
-
return this.type.isTemplate;
|
|
2731
|
-
}
|
|
2732
|
-
get align() {
|
|
2733
|
-
return this.type.isStruct ? this.type.align : 0;
|
|
2734
|
-
}
|
|
2735
|
-
get members() {
|
|
2736
|
-
return this.type.isStruct ? this.type.members : null;
|
|
2737
|
-
}
|
|
2738
|
-
get format() {
|
|
2739
|
-
return this.type.isArray
|
|
2740
|
-
? this.type.format
|
|
2741
|
-
: this.type.isTemplate
|
|
2742
|
-
? this.type.format
|
|
2743
|
-
: null;
|
|
2744
|
-
}
|
|
2745
|
-
get count() {
|
|
2746
|
-
return this.type.isArray ? this.type.count : 0;
|
|
2747
|
-
}
|
|
2748
|
-
get stride() {
|
|
2749
|
-
return this.type.isArray ? this.type.stride : this.size;
|
|
2750
|
-
}
|
|
2751
|
-
}
|
|
2752
|
-
class StructInfo extends TypeInfo {
|
|
2753
|
-
constructor(name, attributes) {
|
|
2754
|
-
super(name, attributes);
|
|
2755
|
-
this.members = [];
|
|
2756
|
-
this.align = 0;
|
|
2757
|
-
}
|
|
2758
|
-
get isStruct() {
|
|
2759
|
-
return true;
|
|
2760
|
-
}
|
|
2761
|
-
}
|
|
2762
|
-
class ArrayInfo extends TypeInfo {
|
|
2763
|
-
constructor(name, attributes) {
|
|
2764
|
-
super(name, attributes);
|
|
2765
|
-
this.count = 0;
|
|
2766
|
-
this.stride = 0;
|
|
2767
|
-
}
|
|
2768
|
-
get isArray() {
|
|
2769
|
-
return true;
|
|
2770
|
-
}
|
|
2771
|
-
}
|
|
2772
|
-
class TemplateInfo extends TypeInfo {
|
|
2773
|
-
constructor(name, format, attributes, access) {
|
|
2774
|
-
super(name, attributes);
|
|
2775
|
-
this.format = format;
|
|
2776
|
-
this.access = access;
|
|
2777
|
-
}
|
|
2778
|
-
get isTemplate() {
|
|
2779
|
-
return true;
|
|
2780
|
-
}
|
|
2781
|
-
}
|
|
2782
|
-
var ResourceType;
|
|
2783
|
-
(function (ResourceType) {
|
|
2784
|
-
ResourceType[ResourceType["Uniform"] = 0] = "Uniform";
|
|
2785
|
-
ResourceType[ResourceType["Storage"] = 1] = "Storage";
|
|
2786
|
-
ResourceType[ResourceType["Texture"] = 2] = "Texture";
|
|
2787
|
-
ResourceType[ResourceType["Sampler"] = 3] = "Sampler";
|
|
2788
|
-
ResourceType[ResourceType["StorageTexture"] = 4] = "StorageTexture";
|
|
2789
|
-
})(ResourceType || (ResourceType = {}));
|
|
2790
|
-
class VariableInfo {
|
|
2791
|
-
constructor(name, type, group, binding, attributes, resourceType, access) {
|
|
2792
|
-
this.name = name;
|
|
2793
|
-
this.type = type;
|
|
2794
|
-
this.group = group;
|
|
2795
|
-
this.binding = binding;
|
|
2796
|
-
this.attributes = attributes;
|
|
2797
|
-
this.resourceType = resourceType;
|
|
2798
|
-
this.access = access;
|
|
2799
|
-
}
|
|
2800
|
-
get isArray() {
|
|
2801
|
-
return this.type.isArray;
|
|
2802
|
-
}
|
|
2803
|
-
get isStruct() {
|
|
2804
|
-
return this.type.isStruct;
|
|
2805
|
-
}
|
|
2806
|
-
get isTemplate() {
|
|
2807
|
-
return this.type.isTemplate;
|
|
2808
|
-
}
|
|
2809
|
-
get size() {
|
|
2810
|
-
return this.type.size;
|
|
2811
|
-
}
|
|
2812
|
-
get align() {
|
|
2813
|
-
return this.type.isStruct ? this.type.align : 0;
|
|
2814
|
-
}
|
|
2815
|
-
get members() {
|
|
2816
|
-
return this.type.isStruct ? this.type.members : null;
|
|
2817
|
-
}
|
|
2818
|
-
get format() {
|
|
2819
|
-
return this.type.isArray
|
|
2820
|
-
? this.type.format
|
|
2821
|
-
: this.type.isTemplate
|
|
2822
|
-
? this.type.format
|
|
2823
|
-
: null;
|
|
2824
|
-
}
|
|
2825
|
-
get count() {
|
|
2826
|
-
return this.type.isArray ? this.type.count : 0;
|
|
2827
|
-
}
|
|
2828
|
-
get stride() {
|
|
2829
|
-
return this.type.isArray ? this.type.stride : this.size;
|
|
2830
|
-
}
|
|
2831
|
-
}
|
|
2832
|
-
class AliasInfo {
|
|
2833
|
-
constructor(name, type) {
|
|
2834
|
-
this.name = name;
|
|
2835
|
-
this.type = type;
|
|
2836
|
-
}
|
|
2837
|
-
}
|
|
2838
|
-
class _TypeSize {
|
|
2839
|
-
constructor(align, size) {
|
|
2840
|
-
this.align = align;
|
|
2841
|
-
this.size = size;
|
|
2842
|
-
}
|
|
2843
|
-
}
|
|
2844
|
-
class InputInfo {
|
|
2845
|
-
constructor(name, type, locationType, location) {
|
|
2846
|
-
this.name = name;
|
|
2847
|
-
this.type = type;
|
|
2848
|
-
this.locationType = locationType;
|
|
2849
|
-
this.location = location;
|
|
2850
|
-
this.interpolation = null;
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
class OutputInfo {
|
|
2854
|
-
constructor(name, type, locationType, location) {
|
|
2855
|
-
this.name = name;
|
|
2856
|
-
this.type = type;
|
|
2857
|
-
this.locationType = locationType;
|
|
2858
|
-
this.location = location;
|
|
2859
|
-
}
|
|
2860
|
-
}
|
|
2861
|
-
class FunctionInfo {
|
|
2862
|
-
constructor(name, stage = null) {
|
|
2863
|
-
this.stage = null;
|
|
2864
|
-
this.inputs = [];
|
|
2865
|
-
this.outputs = [];
|
|
2866
|
-
this.name = name;
|
|
2867
|
-
this.stage = stage;
|
|
2868
|
-
}
|
|
2869
|
-
}
|
|
2870
|
-
class EntryFunctions {
|
|
2871
|
-
constructor() {
|
|
2872
|
-
this.vertex = [];
|
|
2873
|
-
this.fragment = [];
|
|
2874
|
-
this.compute = [];
|
|
2875
|
-
}
|
|
2876
|
-
}
|
|
2877
|
-
class OverrideInfo {
|
|
2878
|
-
constructor(name, type, attributes, id) {
|
|
2879
|
-
this.name = name;
|
|
2880
|
-
this.type = type;
|
|
2881
|
-
this.attributes = attributes;
|
|
2882
|
-
this.id = id;
|
|
2883
|
-
}
|
|
2884
|
-
}
|
|
2885
|
-
class WgslReflect {
|
|
2886
|
-
constructor(code) {
|
|
2887
|
-
/// All top-level uniform vars in the shader.
|
|
2888
|
-
this.uniforms = [];
|
|
2889
|
-
/// All top-level storage vars in the shader.
|
|
2890
|
-
this.storage = [];
|
|
2891
|
-
/// All top-level texture vars in the shader;
|
|
2892
|
-
this.textures = [];
|
|
2893
|
-
// All top-level sampler vars in the shader.
|
|
2894
|
-
this.samplers = [];
|
|
2895
|
-
/// All top-level type aliases in the shader.
|
|
2896
|
-
this.aliases = [];
|
|
2897
|
-
/// All top-level overrides in the shader.
|
|
2898
|
-
this.overrides = [];
|
|
2899
|
-
/// All top-level structs in the shader.
|
|
2900
|
-
this.structs = [];
|
|
2901
|
-
/// All entry functions in the shader: vertex, fragment, and/or compute.
|
|
2902
|
-
this.entry = new EntryFunctions();
|
|
2903
|
-
this._types = new Map();
|
|
2904
|
-
if (code) {
|
|
2905
|
-
this.update(code);
|
|
2906
|
-
}
|
|
2907
|
-
}
|
|
2908
|
-
_isStorageTexture(type) {
|
|
2909
|
-
return (type.name == "texture_storage_1d" ||
|
|
2910
|
-
type.name == "texture_storage_2d" ||
|
|
2911
|
-
type.name == "texture_storage_2d_array" ||
|
|
2912
|
-
type.name == "texture_storage_3d");
|
|
2913
|
-
}
|
|
2914
|
-
update(code) {
|
|
2915
|
-
const parser = new WgslParser();
|
|
2916
|
-
const ast = parser.parse(code);
|
|
2917
|
-
for (const node of ast) {
|
|
2918
|
-
if (node instanceof Struct) {
|
|
2919
|
-
const info = this._getTypeInfo(node, null);
|
|
2920
|
-
if (info instanceof StructInfo) {
|
|
2921
|
-
this.structs.push(info);
|
|
2922
|
-
}
|
|
2923
|
-
continue;
|
|
2924
|
-
}
|
|
2925
|
-
if (node instanceof Alias) {
|
|
2926
|
-
this.aliases.push(this._getAliasInfo(node));
|
|
2927
|
-
continue;
|
|
2928
|
-
}
|
|
2929
|
-
if (node instanceof Override) {
|
|
2930
|
-
const v = node;
|
|
2931
|
-
const id = this._getAttributeNum(v.attributes, "id", 0);
|
|
2932
|
-
const type = v.type != null ? this._getTypeInfo(v.type, v.attributes) : null;
|
|
2933
|
-
this.overrides.push(new OverrideInfo(v.name, type, v.attributes, id));
|
|
2934
|
-
continue;
|
|
2935
|
-
}
|
|
2936
|
-
if (this._isUniformVar(node)) {
|
|
2937
|
-
const v = node;
|
|
2938
|
-
const g = this._getAttributeNum(v.attributes, "group", 0);
|
|
2939
|
-
const b = this._getAttributeNum(v.attributes, "binding", 0);
|
|
2940
|
-
const type = this._getTypeInfo(v.type, v.attributes);
|
|
2941
|
-
const varInfo = new VariableInfo(v.name, type, g, b, v.attributes, ResourceType.Uniform, v.access);
|
|
2942
|
-
this.uniforms.push(varInfo);
|
|
2943
|
-
continue;
|
|
2944
|
-
}
|
|
2945
|
-
if (this._isStorageVar(node)) {
|
|
2946
|
-
const v = node;
|
|
2947
|
-
const g = this._getAttributeNum(v.attributes, "group", 0);
|
|
2948
|
-
const b = this._getAttributeNum(v.attributes, "binding", 0);
|
|
2949
|
-
const type = this._getTypeInfo(v.type, v.attributes);
|
|
2950
|
-
const isStorageTexture = this._isStorageTexture(type);
|
|
2951
|
-
const varInfo = new VariableInfo(v.name, type, g, b, v.attributes, isStorageTexture ? ResourceType.StorageTexture : ResourceType.Storage, v.access);
|
|
2952
|
-
this.storage.push(varInfo);
|
|
2953
|
-
continue;
|
|
2954
|
-
}
|
|
2955
|
-
if (this._isTextureVar(node)) {
|
|
2956
|
-
const v = node;
|
|
2957
|
-
const g = this._getAttributeNum(v.attributes, "group", 0);
|
|
2958
|
-
const b = this._getAttributeNum(v.attributes, "binding", 0);
|
|
2959
|
-
const type = this._getTypeInfo(v.type, v.attributes);
|
|
2960
|
-
const isStorageTexture = this._isStorageTexture(type);
|
|
2961
|
-
const varInfo = new VariableInfo(v.name, type, g, b, v.attributes, isStorageTexture ? ResourceType.StorageTexture : ResourceType.Texture, v.access);
|
|
2962
|
-
if (isStorageTexture) {
|
|
2963
|
-
this.storage.push(varInfo);
|
|
2964
|
-
}
|
|
2965
|
-
else {
|
|
2966
|
-
this.textures.push(varInfo);
|
|
2967
|
-
}
|
|
2968
|
-
continue;
|
|
2969
|
-
}
|
|
2970
|
-
if (this._isSamplerVar(node)) {
|
|
2971
|
-
const v = node;
|
|
2972
|
-
const g = this._getAttributeNum(v.attributes, "group", 0);
|
|
2973
|
-
const b = this._getAttributeNum(v.attributes, "binding", 0);
|
|
2974
|
-
const type = this._getTypeInfo(v.type, v.attributes);
|
|
2975
|
-
const varInfo = new VariableInfo(v.name, type, g, b, v.attributes, ResourceType.Sampler, v.access);
|
|
2976
|
-
this.samplers.push(varInfo);
|
|
2977
|
-
continue;
|
|
2978
|
-
}
|
|
2979
|
-
if (node instanceof Function) {
|
|
2980
|
-
const vertexStage = this._getAttribute(node, "vertex");
|
|
2981
|
-
const fragmentStage = this._getAttribute(node, "fragment");
|
|
2982
|
-
const computeStage = this._getAttribute(node, "compute");
|
|
2983
|
-
const stage = vertexStage || fragmentStage || computeStage;
|
|
2984
|
-
if (stage) {
|
|
2985
|
-
const fn = new FunctionInfo(node.name, stage.name);
|
|
2986
|
-
fn.inputs = this._getInputs(node.args);
|
|
2987
|
-
fn.outputs = this._getOutputs(node.returnType);
|
|
2988
|
-
this.entry[stage.name].push(fn);
|
|
2989
|
-
}
|
|
2990
|
-
continue;
|
|
2991
|
-
}
|
|
2992
|
-
}
|
|
2993
|
-
}
|
|
2994
|
-
getBindGroups() {
|
|
2995
|
-
const groups = [];
|
|
2996
|
-
function _makeRoom(group, binding) {
|
|
2997
|
-
if (group >= groups.length)
|
|
2998
|
-
groups.length = group + 1;
|
|
2999
|
-
if (groups[group] === undefined)
|
|
3000
|
-
groups[group] = [];
|
|
3001
|
-
if (binding >= groups[group].length)
|
|
3002
|
-
groups[group].length = binding + 1;
|
|
3003
|
-
}
|
|
3004
|
-
for (const u of this.uniforms) {
|
|
3005
|
-
_makeRoom(u.group, u.binding);
|
|
3006
|
-
const group = groups[u.group];
|
|
3007
|
-
group[u.binding] = u;
|
|
3008
|
-
}
|
|
3009
|
-
for (const u of this.storage) {
|
|
3010
|
-
_makeRoom(u.group, u.binding);
|
|
3011
|
-
const group = groups[u.group];
|
|
3012
|
-
group[u.binding] = u;
|
|
3013
|
-
}
|
|
3014
|
-
for (const t of this.textures) {
|
|
3015
|
-
_makeRoom(t.group, t.binding);
|
|
3016
|
-
const group = groups[t.group];
|
|
3017
|
-
group[t.binding] = t;
|
|
3018
|
-
}
|
|
3019
|
-
for (const t of this.samplers) {
|
|
3020
|
-
_makeRoom(t.group, t.binding);
|
|
3021
|
-
const group = groups[t.group];
|
|
3022
|
-
group[t.binding] = t;
|
|
3023
|
-
}
|
|
3024
|
-
return groups;
|
|
3025
|
-
}
|
|
3026
|
-
_getOutputs(type, outputs = undefined) {
|
|
3027
|
-
if (outputs === undefined)
|
|
3028
|
-
outputs = [];
|
|
3029
|
-
if (type instanceof Struct) {
|
|
3030
|
-
this._getStructOutputs(type, outputs);
|
|
3031
|
-
}
|
|
3032
|
-
else {
|
|
3033
|
-
const output = this._getOutputInfo(type);
|
|
3034
|
-
if (output !== null)
|
|
3035
|
-
outputs.push(output);
|
|
3036
|
-
}
|
|
3037
|
-
return outputs;
|
|
3038
|
-
}
|
|
3039
|
-
_getStructOutputs(struct, outputs) {
|
|
3040
|
-
for (const m of struct.members) {
|
|
3041
|
-
if (m.type instanceof Struct) {
|
|
3042
|
-
this._getStructOutputs(m.type, outputs);
|
|
3043
|
-
}
|
|
3044
|
-
else {
|
|
3045
|
-
const location = this._getAttribute(m, "location") || this._getAttribute(m, "builtin");
|
|
3046
|
-
if (location !== null) {
|
|
3047
|
-
const typeInfo = this._getTypeInfo(m.type, m.type.attributes);
|
|
3048
|
-
const locationValue = this._parseInt(location.value);
|
|
3049
|
-
const info = new OutputInfo(m.name, typeInfo, location.name, locationValue);
|
|
3050
|
-
outputs.push(info);
|
|
3051
|
-
}
|
|
3052
|
-
}
|
|
3053
|
-
}
|
|
3054
|
-
}
|
|
3055
|
-
_getOutputInfo(type) {
|
|
3056
|
-
const location = this._getAttribute(type, "location") ||
|
|
3057
|
-
this._getAttribute(type, "builtin");
|
|
3058
|
-
if (location !== null) {
|
|
3059
|
-
const typeInfo = this._getTypeInfo(type, type.attributes);
|
|
3060
|
-
const locationValue = this._parseInt(location.value);
|
|
3061
|
-
const info = new OutputInfo("", typeInfo, location.name, locationValue);
|
|
3062
|
-
return info;
|
|
3063
|
-
}
|
|
3064
|
-
return null;
|
|
3065
|
-
}
|
|
3066
|
-
_getInputs(args, inputs = undefined) {
|
|
3067
|
-
if (inputs === undefined)
|
|
3068
|
-
inputs = [];
|
|
3069
|
-
for (const arg of args) {
|
|
3070
|
-
if (arg.type instanceof Struct) {
|
|
3071
|
-
this._getStructInputs(arg.type, inputs);
|
|
3072
|
-
}
|
|
3073
|
-
else {
|
|
3074
|
-
const input = this._getInputInfo(arg);
|
|
3075
|
-
if (input !== null)
|
|
3076
|
-
inputs.push(input);
|
|
3077
|
-
}
|
|
3078
|
-
}
|
|
3079
|
-
return inputs;
|
|
3080
|
-
}
|
|
3081
|
-
_getStructInputs(struct, inputs) {
|
|
3082
|
-
for (const m of struct.members) {
|
|
3083
|
-
if (m.type instanceof Struct) {
|
|
3084
|
-
this._getStructInputs(m.type, inputs);
|
|
3085
|
-
}
|
|
3086
|
-
else {
|
|
3087
|
-
const input = this._getInputInfo(m);
|
|
3088
|
-
if (input !== null)
|
|
3089
|
-
inputs.push(input);
|
|
3090
|
-
}
|
|
3091
|
-
}
|
|
3092
|
-
}
|
|
3093
|
-
_getInputInfo(node) {
|
|
3094
|
-
const location = this._getAttribute(node, "location") ||
|
|
3095
|
-
this._getAttribute(node, "builtin");
|
|
3096
|
-
if (location !== null) {
|
|
3097
|
-
const interpolation = this._getAttribute(node, "interpolation");
|
|
3098
|
-
const type = this._getTypeInfo(node.type, node.attributes);
|
|
3099
|
-
const locationValue = this._parseInt(location.value);
|
|
3100
|
-
const info = new InputInfo(node.name, type, location.name, locationValue);
|
|
3101
|
-
if (interpolation !== null) {
|
|
3102
|
-
info.interpolation = this._parseString(interpolation.value);
|
|
3103
|
-
}
|
|
3104
|
-
return info;
|
|
3105
|
-
}
|
|
3106
|
-
return null;
|
|
3107
|
-
}
|
|
3108
|
-
_parseString(s) {
|
|
3109
|
-
if (s instanceof Array) {
|
|
3110
|
-
s = s[0];
|
|
3111
|
-
}
|
|
3112
|
-
return s;
|
|
3113
|
-
}
|
|
3114
|
-
_parseInt(s) {
|
|
3115
|
-
if (s instanceof Array) {
|
|
3116
|
-
s = s[0];
|
|
3117
|
-
}
|
|
3118
|
-
const n = parseInt(s);
|
|
3119
|
-
return isNaN(n) ? s : n;
|
|
3120
|
-
}
|
|
3121
|
-
_getAlias(name) {
|
|
3122
|
-
for (const a of this.aliases) {
|
|
3123
|
-
if (a.name == name)
|
|
3124
|
-
return a.type;
|
|
3125
|
-
}
|
|
3126
|
-
return null;
|
|
3127
|
-
}
|
|
3128
|
-
_getAliasInfo(node) {
|
|
3129
|
-
return new AliasInfo(node.name, this._getTypeInfo(node.type, null));
|
|
3130
|
-
}
|
|
3131
|
-
_getTypeInfo(type, attributes) {
|
|
3132
|
-
if (this._types.has(type)) {
|
|
3133
|
-
return this._types.get(type);
|
|
3134
|
-
}
|
|
3135
|
-
if (type instanceof ArrayType) {
|
|
3136
|
-
const a = type;
|
|
3137
|
-
const t = this._getTypeInfo(a.format, a.attributes);
|
|
3138
|
-
const info = new ArrayInfo(a.name, attributes);
|
|
3139
|
-
info.format = t;
|
|
3140
|
-
info.count = a.count;
|
|
3141
|
-
this._types.set(type, info);
|
|
3142
|
-
this._updateTypeInfo(info);
|
|
3143
|
-
return info;
|
|
3144
|
-
}
|
|
3145
|
-
if (type instanceof Struct) {
|
|
3146
|
-
const s = type;
|
|
3147
|
-
const info = new StructInfo(s.name, attributes);
|
|
3148
|
-
for (const m of s.members) {
|
|
3149
|
-
const t = this._getTypeInfo(m.type, m.attributes);
|
|
3150
|
-
info.members.push(new MemberInfo(m.name, t, m.attributes));
|
|
3151
|
-
}
|
|
3152
|
-
this._types.set(type, info);
|
|
3153
|
-
this._updateTypeInfo(info);
|
|
3154
|
-
return info;
|
|
3155
|
-
}
|
|
3156
|
-
if (type instanceof SamplerType) {
|
|
3157
|
-
const s = type;
|
|
3158
|
-
const formatIsType = s.format instanceof Type;
|
|
3159
|
-
const format = s.format
|
|
3160
|
-
? formatIsType
|
|
3161
|
-
? this._getTypeInfo(s.format, null)
|
|
3162
|
-
: new TypeInfo(s.format, null)
|
|
3163
|
-
: null;
|
|
3164
|
-
const info = new TemplateInfo(s.name, format, attributes, s.access);
|
|
3165
|
-
this._types.set(type, info);
|
|
3166
|
-
this._updateTypeInfo(info);
|
|
3167
|
-
return info;
|
|
3168
|
-
}
|
|
3169
|
-
if (type instanceof TemplateType) {
|
|
3170
|
-
const t = type;
|
|
3171
|
-
const format = t.format ? this._getTypeInfo(t.format, null) : null;
|
|
3172
|
-
const info = new TemplateInfo(t.name, format, attributes, t.access);
|
|
3173
|
-
this._types.set(type, info);
|
|
3174
|
-
this._updateTypeInfo(info);
|
|
3175
|
-
return info;
|
|
3176
|
-
}
|
|
3177
|
-
const info = new TypeInfo(type.name, attributes);
|
|
3178
|
-
this._types.set(type, info);
|
|
3179
|
-
this._updateTypeInfo(info);
|
|
3180
|
-
return info;
|
|
3181
|
-
}
|
|
3182
|
-
_updateTypeInfo(type) {
|
|
3183
|
-
var _a, _b;
|
|
3184
|
-
const typeSize = this._getTypeSize(type);
|
|
3185
|
-
type.size = (_a = typeSize === null || typeSize === void 0 ? void 0 : typeSize.size) !== null && _a !== void 0 ? _a : 0;
|
|
3186
|
-
if (type instanceof ArrayInfo) {
|
|
3187
|
-
const formatInfo = this._getTypeSize(type["format"]);
|
|
3188
|
-
type.stride = (_b = formatInfo === null || formatInfo === void 0 ? void 0 : formatInfo.size) !== null && _b !== void 0 ? _b : 0;
|
|
3189
|
-
this._updateTypeInfo(type["format"]);
|
|
3190
|
-
}
|
|
3191
|
-
if (type instanceof StructInfo) {
|
|
3192
|
-
this._updateStructInfo(type);
|
|
3193
|
-
}
|
|
3194
|
-
}
|
|
3195
|
-
_updateStructInfo(struct) {
|
|
3196
|
-
var _a;
|
|
3197
|
-
let offset = 0;
|
|
3198
|
-
let lastSize = 0;
|
|
3199
|
-
let lastOffset = 0;
|
|
3200
|
-
let structAlign = 0;
|
|
3201
|
-
for (let mi = 0, ml = struct.members.length; mi < ml; ++mi) {
|
|
3202
|
-
const member = struct.members[mi];
|
|
3203
|
-
const sizeInfo = this._getTypeSize(member);
|
|
3204
|
-
if (!sizeInfo)
|
|
3205
|
-
continue;
|
|
3206
|
-
(_a = this._getAlias(member.type.name)) !== null && _a !== void 0 ? _a : member.type;
|
|
3207
|
-
const align = sizeInfo.align;
|
|
3208
|
-
const size = sizeInfo.size;
|
|
3209
|
-
offset = this._roundUp(align, offset + lastSize);
|
|
3210
|
-
lastSize = size;
|
|
3211
|
-
lastOffset = offset;
|
|
3212
|
-
structAlign = Math.max(structAlign, align);
|
|
3213
|
-
member.offset = offset;
|
|
3214
|
-
member.size = size;
|
|
3215
|
-
this._updateTypeInfo(member.type);
|
|
3216
|
-
}
|
|
3217
|
-
struct.size = this._roundUp(structAlign, lastOffset + lastSize);
|
|
3218
|
-
struct.align = structAlign;
|
|
3219
|
-
}
|
|
3220
|
-
_getTypeSize(type) {
|
|
3221
|
-
var _a;
|
|
3222
|
-
if (type === null || type === undefined)
|
|
3223
|
-
return null;
|
|
3224
|
-
const explicitSize = this._getAttributeNum(type.attributes, "size", 0);
|
|
3225
|
-
const explicitAlign = this._getAttributeNum(type.attributes, "align", 0);
|
|
3226
|
-
if (type instanceof MemberInfo)
|
|
3227
|
-
type = type.type;
|
|
3228
|
-
if (type instanceof TypeInfo) {
|
|
3229
|
-
const alias = this._getAlias(type.name);
|
|
3230
|
-
if (alias !== null) {
|
|
3231
|
-
type = alias;
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
|
-
{
|
|
3235
|
-
const info = WgslReflect._typeInfo[type.name];
|
|
3236
|
-
if (info !== undefined) {
|
|
3237
|
-
const divisor = type["format"] === "f16" ? 2 : 1;
|
|
3238
|
-
return new _TypeSize(Math.max(explicitAlign, info.align / divisor), Math.max(explicitSize, info.size / divisor));
|
|
3239
|
-
}
|
|
3240
|
-
}
|
|
3241
|
-
{
|
|
3242
|
-
const info = WgslReflect._typeInfo[type.name.substring(0, type.name.length - 1)];
|
|
3243
|
-
if (info) {
|
|
3244
|
-
const divisor = type.name[type.name.length - 1] === "h" ? 2 : 1;
|
|
3245
|
-
return new _TypeSize(Math.max(explicitAlign, info.align / divisor), Math.max(explicitSize, info.size / divisor));
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
if (type instanceof ArrayInfo) {
|
|
3249
|
-
let arrayType = type;
|
|
3250
|
-
let align = 8;
|
|
3251
|
-
let size = 8;
|
|
3252
|
-
// Type AlignOf(T) Sizeof(T)
|
|
3253
|
-
// array<E, N> AlignOf(E) N * roundUp(AlignOf(E), SizeOf(E))
|
|
3254
|
-
// array<E> AlignOf(E) N * roundUp(AlignOf(E), SizeOf(E)) (N determined at runtime)
|
|
3255
|
-
//
|
|
3256
|
-
// @stride(Q)
|
|
3257
|
-
// array<E, N> AlignOf(E) N * Q
|
|
3258
|
-
//
|
|
3259
|
-
// @stride(Q)
|
|
3260
|
-
// array<E> AlignOf(E) Nruntime * Q
|
|
3261
|
-
//const E = type.format.name;
|
|
3262
|
-
const E = this._getTypeSize(arrayType.format);
|
|
3263
|
-
if (E !== null) {
|
|
3264
|
-
size = E.size;
|
|
3265
|
-
align = E.align;
|
|
3266
|
-
}
|
|
3267
|
-
const N = arrayType.count;
|
|
3268
|
-
const stride = this._getAttributeNum((_a = type === null || type === void 0 ? void 0 : type.attributes) !== null && _a !== void 0 ? _a : null, "stride", this._roundUp(align, size));
|
|
3269
|
-
size = N * stride;
|
|
3270
|
-
if (explicitSize)
|
|
3271
|
-
size = explicitSize;
|
|
3272
|
-
return new _TypeSize(Math.max(explicitAlign, align), Math.max(explicitSize, size));
|
|
3273
|
-
}
|
|
3274
|
-
if (type instanceof StructInfo) {
|
|
3275
|
-
let align = 0;
|
|
3276
|
-
let size = 0;
|
|
3277
|
-
// struct S AlignOf: max(AlignOfMember(S, M1), ... , AlignOfMember(S, MN))
|
|
3278
|
-
// SizeOf: roundUp(AlignOf(S), OffsetOfMember(S, L) + SizeOfMember(S, L))
|
|
3279
|
-
// Where L is the last member of the structure
|
|
3280
|
-
let offset = 0;
|
|
3281
|
-
let lastSize = 0;
|
|
3282
|
-
let lastOffset = 0;
|
|
3283
|
-
for (const m of type.members) {
|
|
3284
|
-
const mi = this._getTypeSize(m.type);
|
|
3285
|
-
if (mi !== null) {
|
|
3286
|
-
align = Math.max(mi.align, align);
|
|
3287
|
-
offset = this._roundUp(mi.align, offset + lastSize);
|
|
3288
|
-
lastSize = mi.size;
|
|
3289
|
-
lastOffset = offset;
|
|
3290
|
-
}
|
|
3291
|
-
}
|
|
3292
|
-
size = this._roundUp(align, lastOffset + lastSize);
|
|
3293
|
-
return new _TypeSize(Math.max(explicitAlign, align), Math.max(explicitSize, size));
|
|
3294
|
-
}
|
|
3295
|
-
return null;
|
|
3296
|
-
}
|
|
3297
|
-
_isUniformVar(node) {
|
|
3298
|
-
return node instanceof Var && node.storage == "uniform";
|
|
3299
|
-
}
|
|
3300
|
-
_isStorageVar(node) {
|
|
3301
|
-
return node instanceof Var && node.storage == "storage";
|
|
3302
|
-
}
|
|
3303
|
-
_isTextureVar(node) {
|
|
3304
|
-
return (node instanceof Var &&
|
|
3305
|
-
node.type !== null &&
|
|
3306
|
-
WgslReflect._textureTypes.indexOf(node.type.name) != -1);
|
|
3307
|
-
}
|
|
3308
|
-
_isSamplerVar(node) {
|
|
3309
|
-
return (node instanceof Var &&
|
|
3310
|
-
node.type !== null &&
|
|
3311
|
-
WgslReflect._samplerTypes.indexOf(node.type.name) != -1);
|
|
3312
|
-
}
|
|
3313
|
-
_getAttribute(node, name) {
|
|
3314
|
-
const obj = node;
|
|
3315
|
-
if (!obj || !obj["attributes"])
|
|
3316
|
-
return null;
|
|
3317
|
-
const attrs = obj["attributes"];
|
|
3318
|
-
for (let a of attrs) {
|
|
3319
|
-
if (a.name == name)
|
|
3320
|
-
return a;
|
|
3321
|
-
}
|
|
3322
|
-
return null;
|
|
3323
|
-
}
|
|
3324
|
-
_getAttributeNum(attributes, name, defaultValue) {
|
|
3325
|
-
if (attributes === null)
|
|
3326
|
-
return defaultValue;
|
|
3327
|
-
for (let a of attributes) {
|
|
3328
|
-
if (a.name == name) {
|
|
3329
|
-
let v = a !== null && a.value !== null ? a.value : defaultValue;
|
|
3330
|
-
if (v instanceof Array) {
|
|
3331
|
-
v = v[0];
|
|
3332
|
-
}
|
|
3333
|
-
if (typeof v === "number") {
|
|
3334
|
-
return v;
|
|
3335
|
-
}
|
|
3336
|
-
if (typeof v === "string") {
|
|
3337
|
-
return parseInt(v);
|
|
3338
|
-
}
|
|
3339
|
-
return defaultValue;
|
|
3340
|
-
}
|
|
3341
|
-
}
|
|
3342
|
-
return defaultValue;
|
|
3343
|
-
}
|
|
3344
|
-
_roundUp(k, n) {
|
|
3345
|
-
return Math.ceil(n / k) * k;
|
|
3346
|
-
}
|
|
3347
|
-
}
|
|
3348
|
-
// Type AlignOf(T) Sizeof(T)
|
|
3349
|
-
// i32, u32, or f32 4 4
|
|
3350
|
-
// atomic<T> 4 4
|
|
3351
|
-
// vec2<T> 8 8
|
|
3352
|
-
// vec3<T> 16 12
|
|
3353
|
-
// vec4<T> 16 16
|
|
3354
|
-
// mat2x2<f32> 8 16
|
|
3355
|
-
// mat3x2<f32> 8 24
|
|
3356
|
-
// mat4x2<f32> 8 32
|
|
3357
|
-
// mat2x3<f32> 16 32
|
|
3358
|
-
// mat3x3<f32> 16 48
|
|
3359
|
-
// mat4x3<f32> 16 64
|
|
3360
|
-
// mat2x4<f32> 16 32
|
|
3361
|
-
// mat3x4<f32> 16 48
|
|
3362
|
-
// mat4x4<f32> 16 64
|
|
3363
|
-
WgslReflect._typeInfo = {
|
|
3364
|
-
f16: { align: 2, size: 2 },
|
|
3365
|
-
i32: { align: 4, size: 4 },
|
|
3366
|
-
u32: { align: 4, size: 4 },
|
|
3367
|
-
f32: { align: 4, size: 4 },
|
|
3368
|
-
atomic: { align: 4, size: 4 },
|
|
3369
|
-
vec2: { align: 8, size: 8 },
|
|
3370
|
-
vec3: { align: 16, size: 12 },
|
|
3371
|
-
vec4: { align: 16, size: 16 },
|
|
3372
|
-
mat2x2: { align: 8, size: 16 },
|
|
3373
|
-
mat3x2: { align: 8, size: 24 },
|
|
3374
|
-
mat4x2: { align: 8, size: 32 },
|
|
3375
|
-
mat2x3: { align: 16, size: 32 },
|
|
3376
|
-
mat3x3: { align: 16, size: 48 },
|
|
3377
|
-
mat4x3: { align: 16, size: 64 },
|
|
3378
|
-
mat2x4: { align: 16, size: 32 },
|
|
3379
|
-
mat3x4: { align: 16, size: 48 },
|
|
3380
|
-
mat4x4: { align: 16, size: 64 },
|
|
3381
|
-
};
|
|
3382
|
-
WgslReflect._textureTypes = TokenTypes.any_texture_type.map((t) => {
|
|
3383
|
-
return t.name;
|
|
3384
|
-
});
|
|
3385
|
-
WgslReflect._samplerTypes = TokenTypes.sampler_type.map((t) => {
|
|
3386
|
-
return t.name;
|
|
3387
|
-
});
|
|
3388
|
-
export { Alias, AliasInfo, Argument, ArrayInfo, ArrayType, Assign, AssignOperator, Attribute, BinaryOperator, BitcastExpr, Break, Call, CallExpr, Case, Const, ConstExpr, Continue, Continuing, CreateExpr, Default, Discard, ElseIf, Enable, EntryFunctions, Expression, For, Function, FunctionInfo, GroupingExpr, If, Increment, IncrementOperator, InputInfo, Let, LiteralExpr, Loop, Member, MemberInfo, Node, Operator, OutputInfo, Override, OverrideInfo, ParseContext, PointerType, ResourceType, Return, SamplerType, Statement, StaticAssert, StringExpr, Struct, StructInfo, Switch, SwitchCase, TemplateInfo, TemplateType, Token, TokenClass, TokenType, TokenTypes, Type, TypeInfo, TypecastExpr, UnaryOperator, Var, VariableExpr, VariableInfo, WgslParser, WgslReflect, WgslScanner, While };
|
|
3389
|
-
//# sourceMappingURL=wgsl_reflect.module.js.map
|