wesl 0.7.21 → 0.7.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +44 -2
- package/dist/index.js +356 -327
- package/package.json +1 -9
- package/src/BindIdents.ts +47 -46
- package/src/LowerAndEmit.ts +1 -20
- package/src/Scope.ts +3 -1
- package/src/StandardTypes.ts +19 -0
- package/src/discovery/FindUnboundIdents.ts +69 -10
- package/src/index.ts +1 -0
- package/src/test/DiscoverModules.test.ts +113 -0
- package/src/test/FindUnboundIdents.test.ts +71 -0
- package/src/test/LinkPackage.test.ts +23 -17
package/dist/index.js
CHANGED
|
@@ -334,8 +334,8 @@ function throwClickableError(params) {
|
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
/** Warn the user about an identifier and throw a clickable exception */
|
|
337
|
-
function failIdent(ident
|
|
338
|
-
const { refIdentElem, originalName } = ident
|
|
337
|
+
function failIdent(ident, msg) {
|
|
338
|
+
const { refIdentElem, originalName } = ident;
|
|
339
339
|
const baseMessage = msg ?? `'${originalName}'`;
|
|
340
340
|
if (refIdentElem) failIdentElem(refIdentElem, baseMessage);
|
|
341
341
|
else throw new Error(baseMessage);
|
|
@@ -504,11 +504,78 @@ function childIdent(child) {
|
|
|
504
504
|
}
|
|
505
505
|
|
|
506
506
|
//#endregion
|
|
507
|
-
//#region src/
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
507
|
+
//#region src/StandardTypes.ts
|
|
508
|
+
const stdFns = `bitcast all any select arrayLength
|
|
509
|
+
abs acos acosh asin asinh atan atanh atan2 ceil clamp cos cosh
|
|
510
|
+
countLeadingZeros countOneBits countTrailingZeros cross
|
|
511
|
+
degrees determinant distance dot dot4U8Packed dot4I8Packed
|
|
512
|
+
exp exp2 extractBits faceForward firstLeadingBit firstTrailingBit
|
|
513
|
+
floor fma fract frexp insertBits inverseSqrt ldexp length log log2
|
|
514
|
+
max min mix modf normalize pow quantizeToF16 radians reflect refract
|
|
515
|
+
reverseBits round saturate sign sin sinh smoothstep sqrt step tan tanh
|
|
516
|
+
transpose trunc
|
|
517
|
+
dpdx dpdxCoarse dpdxFine dpdy dpdyCoarse dpdyFine fwidth
|
|
518
|
+
fwidthCoarse fwidthFine
|
|
519
|
+
textureDimensions textureGather textureGatherCompare textureLoad
|
|
520
|
+
textureNumLayers textureNumLevels textureNumSamples
|
|
521
|
+
textureSample textureSampleBias textureSampleCompare textureSampleCompareLevel
|
|
522
|
+
textureSampleGrad textureSampleLevel textureSampleBaseClampToEdge
|
|
523
|
+
textureStore
|
|
524
|
+
atomicLoad atomicStore atomicAdd atomicSub atomicMax atomicMin
|
|
525
|
+
atomicAnd atomicOr atomicXor atomicExchange atomicCompareExchangeWeak
|
|
526
|
+
pack4x8snorm pack4x8unorm pack4xI8 pack4xU8 pack4xI8Clamp pack4xU8Clamp
|
|
527
|
+
pack2x16snorm pack2x16unorm pack2x16float
|
|
528
|
+
unpack4x8snorm unpack4x8unorm unpack4xI8 unpack4xU8
|
|
529
|
+
unpack2x16snorm unpack2x16unorm unpack2x16float
|
|
530
|
+
storageBarrier textureBarrier workgroupBarrier workgroupUniformLoad
|
|
531
|
+
subgroupAdd subgroupAll subgroupAnd subgroupAny subgroupBallot
|
|
532
|
+
subgroupBroadcast subgroupBroadcastFirst subgroupElect
|
|
533
|
+
subgroupExclusiveAdd subgroupExclusiveMul subgroupInclusiveAdd
|
|
534
|
+
subgroupInclusiveMul subgroupMax subgroupMin subgroupMul subgroupOr
|
|
535
|
+
subgroupShuffle subgroupShuffleUp subgroupShuffleXor subgroupXor
|
|
536
|
+
quadBroadcast quadSwapDiagonal quadSwapX quadSwapY`.split(/\s+/);
|
|
537
|
+
const sampledTextureTypes = `
|
|
538
|
+
texture_1d texture_2d texture_2d_array texture_3d
|
|
539
|
+
texture_cube texture_cube_array
|
|
540
|
+
`;
|
|
541
|
+
const multisampledTextureTypes = `
|
|
542
|
+
texture_multisampled_2d texture_depth_multisampled_2d
|
|
543
|
+
`;
|
|
544
|
+
const textureStorageTypes = `
|
|
545
|
+
texture_storage_1d texture_storage_2d texture_storage_2d_array
|
|
546
|
+
texture_storage_3d
|
|
547
|
+
`;
|
|
548
|
+
const stdTypes = `array atomic bool f16 f32 i32
|
|
549
|
+
mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4
|
|
550
|
+
mat2x2f mat2x3f mat2x4f mat3x2f mat3x3f mat3x4f
|
|
551
|
+
mat4x2f mat4x3f mat4x4f
|
|
552
|
+
mat2x2h mat2x3h mat2x4h mat3x2h mat3x3h mat3x4h
|
|
553
|
+
mat4x2h mat4x3h mat4x4h
|
|
554
|
+
u32 vec2 vec3 vec4 ptr
|
|
555
|
+
vec2i vec3i vec4i vec2u vec3u vec4u
|
|
556
|
+
vec2f vec3f vec4f vec2h vec3h vec4h
|
|
557
|
+
${sampledTextureTypes}
|
|
558
|
+
${multisampledTextureTypes}
|
|
559
|
+
texture_external
|
|
560
|
+
${textureStorageTypes}
|
|
561
|
+
texture_depth_2d texture_depth_2d_array texture_depth_cube
|
|
562
|
+
texture_depth_cube_array
|
|
563
|
+
sampler sampler_comparison
|
|
564
|
+
rgba8unorm rgba8snorm rgba8uint rgba8sint
|
|
565
|
+
rgba16uint rgba16sint rgba16float
|
|
566
|
+
r32uint r32sint r32float rg32uint rg32sint rg32float
|
|
567
|
+
rgba32uint rgba32sint rgba32float
|
|
568
|
+
bgra8unorm`.split(/\s+/);
|
|
569
|
+
/** https://www.w3.org/TR/WGSL/#predeclared-enumerants */
|
|
570
|
+
const stdEnumerants = `read write read_write
|
|
571
|
+
function private workgroup uniform storage
|
|
572
|
+
rgba8unorm rgba8snorm rgba8uint rgba8sint
|
|
573
|
+
rgba16uint rgba16sint rgba16float
|
|
574
|
+
r32uint r32sint r32float rg32uint rg32sint rg32float
|
|
575
|
+
rgba32uint rgba32sint rgba32float bgra8unorm`.split(/\s+/);
|
|
576
|
+
/** WGSL standard attributes whose params need binding (e.g., @workgroup_size).
|
|
577
|
+
* See: https://www.w3.org/TR/WGSL/#attributes */
|
|
578
|
+
const wgslStandardAttributes = new Set([
|
|
512
579
|
"align",
|
|
513
580
|
"binding",
|
|
514
581
|
"blend_src",
|
|
@@ -524,6 +591,21 @@ const wgslStandardAttributes$1 = new Set([
|
|
|
524
591
|
"vertex",
|
|
525
592
|
"workgroup_size"
|
|
526
593
|
]);
|
|
594
|
+
/** return true if the name is for a built in type (not a user struct) */
|
|
595
|
+
function stdType(name) {
|
|
596
|
+
return stdTypes.includes(name);
|
|
597
|
+
}
|
|
598
|
+
/** return true if the name is for a built in fn (not a user function) */
|
|
599
|
+
function stdFn(name) {
|
|
600
|
+
return stdFns.includes(name) || stdType(name);
|
|
601
|
+
}
|
|
602
|
+
/** return true if the name is for a built in enumerant */
|
|
603
|
+
function stdEnumerant(name) {
|
|
604
|
+
return stdEnumerants.includes(name);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
//#endregion
|
|
608
|
+
//#region src/LowerAndEmit.ts
|
|
527
609
|
/** Traverse the AST, starting from root elements, emitting WGSL for each. */
|
|
528
610
|
function lowerAndEmit(params) {
|
|
529
611
|
const { srcBuilder, rootElems, conditions } = params;
|
|
@@ -717,13 +799,13 @@ function emitContentsWithTrimming(elem, ctx) {
|
|
|
717
799
|
const validElements = filterValidElements(elem.contents, ctx.conditions);
|
|
718
800
|
const firstEmit = validElements.findIndex((e) => !isConditionalAttr(e));
|
|
719
801
|
const lastEmit = validElements.findLastIndex((e) => !isConditionalAttr(e));
|
|
720
|
-
validElements.forEach((elem
|
|
721
|
-
if (elem
|
|
722
|
-
let text = elem
|
|
802
|
+
validElements.forEach((elem, i) => {
|
|
803
|
+
if (elem.kind === "text") {
|
|
804
|
+
let text = elem.srcModule.src.slice(elem.start, elem.end);
|
|
723
805
|
if (i === firstEmit) text = text.trimStart();
|
|
724
806
|
if (i === lastEmit) text = text.trimEnd();
|
|
725
|
-
if (text) ctx.srcBuilder.add(text, elem
|
|
726
|
-
} else lowerAndEmitElem(elem
|
|
807
|
+
if (text) ctx.srcBuilder.add(text, elem.start, elem.end);
|
|
808
|
+
} else lowerAndEmitElem(elem, ctx);
|
|
727
809
|
});
|
|
728
810
|
}
|
|
729
811
|
function isConditionalAttr(e) {
|
|
@@ -803,7 +885,7 @@ function emitAttribute(e, ctx) {
|
|
|
803
885
|
const { kind } = e.attribute;
|
|
804
886
|
if (kind === "@if" || kind === "@elif" || kind === "@else") return false;
|
|
805
887
|
if (kind === "@attribute") {
|
|
806
|
-
if (!wgslStandardAttributes
|
|
888
|
+
if (!wgslStandardAttributes.has(e.attribute.name)) return false;
|
|
807
889
|
emitStandardAttribute(e, ctx);
|
|
808
890
|
return true;
|
|
809
891
|
}
|
|
@@ -885,13 +967,13 @@ function displayName(declIdent) {
|
|
|
885
967
|
return declIdent.mangledName || declIdent.originalName;
|
|
886
968
|
}
|
|
887
969
|
/** Trace through refersTo links until we find the declaration. */
|
|
888
|
-
function findDecl(ident
|
|
889
|
-
let i = ident
|
|
970
|
+
function findDecl(ident) {
|
|
971
|
+
let i = ident;
|
|
890
972
|
do {
|
|
891
973
|
if (i.kind === "decl") return i;
|
|
892
974
|
i = i.refersTo;
|
|
893
975
|
} while (i);
|
|
894
|
-
throw new Error(`unresolved identifer: ${ident
|
|
976
|
+
throw new Error(`unresolved identifer: ${ident.originalName}`);
|
|
895
977
|
}
|
|
896
978
|
|
|
897
979
|
//#endregion
|
|
@@ -1122,7 +1204,7 @@ function scopeToString(scope, indent = 0, shortIdents = true) {
|
|
|
1122
1204
|
if (attrStrings) str.add(attrStrings + " ");
|
|
1123
1205
|
if (kind === "partial") str.add("-");
|
|
1124
1206
|
str.add("{ ");
|
|
1125
|
-
const last
|
|
1207
|
+
const last = contents.length - 1;
|
|
1126
1208
|
let lastWasScope = false;
|
|
1127
1209
|
let hasBlock = false;
|
|
1128
1210
|
contents.forEach((elem, i) => {
|
|
@@ -1135,10 +1217,10 @@ function scopeToString(scope, indent = 0, shortIdents = true) {
|
|
|
1135
1217
|
} else {
|
|
1136
1218
|
if (lastWasScope) str.add(" ");
|
|
1137
1219
|
lastWasScope = false;
|
|
1138
|
-
const ident
|
|
1139
|
-
if (shortIdents) str.add(identShortString(ident
|
|
1140
|
-
else str.add(identToString(ident
|
|
1141
|
-
if (i < last
|
|
1220
|
+
const ident = elem;
|
|
1221
|
+
if (shortIdents) str.add(identShortString(ident));
|
|
1222
|
+
else str.add(identToString(ident));
|
|
1223
|
+
if (i < last) str.add(" ");
|
|
1142
1224
|
}
|
|
1143
1225
|
});
|
|
1144
1226
|
if (!hasBlock && str.oneLine) str.add(" }");
|
|
@@ -1154,17 +1236,17 @@ function scopeToStringLong(scope) {
|
|
|
1154
1236
|
return scopeToString(scope, 0, false);
|
|
1155
1237
|
}
|
|
1156
1238
|
/** name of an identifier, with decls prefixed with '%' */
|
|
1157
|
-
function identShortString(ident
|
|
1158
|
-
const { kind, originalName } = ident
|
|
1239
|
+
function identShortString(ident) {
|
|
1240
|
+
const { kind, originalName } = ident;
|
|
1159
1241
|
return `${kind === "decl" ? "%" : ""}${originalName}`;
|
|
1160
1242
|
}
|
|
1161
|
-
function identToString(ident
|
|
1162
|
-
if (!ident
|
|
1163
|
-
const { kind, originalName } = ident
|
|
1164
|
-
const idStr = ident
|
|
1165
|
-
if (kind === "ref") return `${originalName} ${idStr} -> ${identToString(ident
|
|
1243
|
+
function identToString(ident) {
|
|
1244
|
+
if (!ident) return JSON.stringify(ident);
|
|
1245
|
+
const { kind, originalName } = ident;
|
|
1246
|
+
const idStr = ident.id ? `#${ident.id}` : "";
|
|
1247
|
+
if (kind === "ref") return `${originalName} ${idStr} -> ${identToString(ident.refersTo)}`;
|
|
1166
1248
|
else {
|
|
1167
|
-
const { mangledName } = ident
|
|
1249
|
+
const { mangledName } = ident;
|
|
1168
1250
|
return `%${originalName}${mangledName ? `(${mangledName})` : ""} ${idStr} `;
|
|
1169
1251
|
}
|
|
1170
1252
|
}
|
|
@@ -1655,11 +1737,11 @@ function parseIdent(ctx, conditionRef) {
|
|
|
1655
1737
|
const path = parseModulePath(ctx.stream);
|
|
1656
1738
|
if (!path) return null;
|
|
1657
1739
|
const { parts, start, end } = path;
|
|
1658
|
-
const ident
|
|
1659
|
-
if (conditionRef) ident
|
|
1660
|
-
const refIdentElem = makeRefIdentElem(ctx, ident
|
|
1740
|
+
const ident = ctx.createRefIdent(parts.join("::"));
|
|
1741
|
+
if (conditionRef) ident.conditionRef = true;
|
|
1742
|
+
const refIdentElem = makeRefIdentElem(ctx, ident, start, end);
|
|
1661
1743
|
if (!conditionRef) {
|
|
1662
|
-
ctx.saveIdent(ident
|
|
1744
|
+
ctx.saveIdent(ident);
|
|
1663
1745
|
ctx.addElem(refIdentElem);
|
|
1664
1746
|
}
|
|
1665
1747
|
return refIdentElem;
|
|
@@ -2202,8 +2284,8 @@ function parseElseChain(ctx) {
|
|
|
2202
2284
|
while (stream.matchText("else")) {
|
|
2203
2285
|
if (stream.matchText("if")) {
|
|
2204
2286
|
expectExpression(ctx, "Expected expression after 'else if'");
|
|
2205
|
-
const body
|
|
2206
|
-
ctx.addElem(body
|
|
2287
|
+
const body = expectCompound(ctx, "Expected '{' after else if");
|
|
2288
|
+
ctx.addElem(body);
|
|
2207
2289
|
continue;
|
|
2208
2290
|
}
|
|
2209
2291
|
const body = expectCompound(ctx, "Expected '{' after else");
|
|
@@ -3162,8 +3244,8 @@ var ParsingContext = class {
|
|
|
3162
3244
|
declElem: null
|
|
3163
3245
|
};
|
|
3164
3246
|
}
|
|
3165
|
-
saveIdent(ident
|
|
3166
|
-
this.state.context.scope.contents.push(ident
|
|
3247
|
+
saveIdent(ident) {
|
|
3248
|
+
this.state.context.scope.contents.push(ident);
|
|
3167
3249
|
}
|
|
3168
3250
|
};
|
|
3169
3251
|
|
|
@@ -3252,7 +3334,7 @@ function toRegexSource(nameExp) {
|
|
|
3252
3334
|
}
|
|
3253
3335
|
}
|
|
3254
3336
|
function verifyNonCapturing(name, exp) {
|
|
3255
|
-
if (
|
|
3337
|
+
if (new RegExp("|" + exp.source).exec("").length > 1) throw new Error(`match expression groups must be non-capturing: ${name}: /${exp.source}/. Use (?:...) instead.`);
|
|
3256
3338
|
}
|
|
3257
3339
|
const regexSpecials = /[$+*.?|(){}[\]\\/^]/g;
|
|
3258
3340
|
function escapeRegex(s) {
|
|
@@ -3595,115 +3677,16 @@ function flatImports(ast, conditions) {
|
|
|
3595
3677
|
return flat;
|
|
3596
3678
|
}
|
|
3597
3679
|
|
|
3598
|
-
//#endregion
|
|
3599
|
-
//#region src/StandardTypes.ts
|
|
3600
|
-
const stdFns = `bitcast all any select arrayLength
|
|
3601
|
-
abs acos acosh asin asinh atan atanh atan2 ceil clamp cos cosh
|
|
3602
|
-
countLeadingZeros countOneBits countTrailingZeros cross
|
|
3603
|
-
degrees determinant distance dot dot4U8Packed dot4I8Packed
|
|
3604
|
-
exp exp2 extractBits faceForward firstLeadingBit firstTrailingBit
|
|
3605
|
-
floor fma fract frexp insertBits inverseSqrt ldexp length log log2
|
|
3606
|
-
max min mix modf normalize pow quantizeToF16 radians reflect refract
|
|
3607
|
-
reverseBits round saturate sign sin sinh smoothstep sqrt step tan tanh
|
|
3608
|
-
transpose trunc
|
|
3609
|
-
dpdx dpdxCoarse dpdxFine dpdy dpdyCoarse dpdyFine fwidth
|
|
3610
|
-
fwidthCoarse fwidthFine
|
|
3611
|
-
textureDimensions textureGather textureGatherCompare textureLoad
|
|
3612
|
-
textureNumLayers textureNumLevels textureNumSamples
|
|
3613
|
-
textureSample textureSampleBias textureSampleCompare textureSampleCompareLevel
|
|
3614
|
-
textureSampleGrad textureSampleLevel textureSampleBaseClampToEdge
|
|
3615
|
-
textureStore
|
|
3616
|
-
atomicLoad atomicStore atomicAdd atomicSub atomicMax atomicMin
|
|
3617
|
-
atomicAnd atomicOr atomicXor atomicExchange atomicCompareExchangeWeak
|
|
3618
|
-
pack4x8snorm pack4x8unorm pack4xI8 pack4xU8 pack4xI8Clamp pack4xU8Clamp
|
|
3619
|
-
pack2x16snorm pack2x16unorm pack2x16float
|
|
3620
|
-
unpack4x8snorm unpack4x8unorm unpack4xI8 unpack4xU8
|
|
3621
|
-
unpack2x16snorm unpack2x16unorm unpack2x16float
|
|
3622
|
-
storageBarrier textureBarrier workgroupBarrier workgroupUniformLoad
|
|
3623
|
-
subgroupAdd subgroupAll subgroupAnd subgroupAny subgroupBallot
|
|
3624
|
-
subgroupBroadcast subgroupBroadcastFirst subgroupElect
|
|
3625
|
-
subgroupExclusiveAdd subgroupExclusiveMul subgroupInclusiveAdd
|
|
3626
|
-
subgroupInclusiveMul subgroupMax subgroupMin subgroupMul subgroupOr
|
|
3627
|
-
subgroupShuffle subgroupShuffleUp subgroupShuffleXor subgroupXor
|
|
3628
|
-
quadBroadcast quadSwapDiagonal quadSwapX quadSwapY`.split(/\s+/);
|
|
3629
|
-
const sampledTextureTypes = `
|
|
3630
|
-
texture_1d texture_2d texture_2d_array texture_3d
|
|
3631
|
-
texture_cube texture_cube_array
|
|
3632
|
-
`;
|
|
3633
|
-
const multisampledTextureTypes = `
|
|
3634
|
-
texture_multisampled_2d texture_depth_multisampled_2d
|
|
3635
|
-
`;
|
|
3636
|
-
const textureStorageTypes = `
|
|
3637
|
-
texture_storage_1d texture_storage_2d texture_storage_2d_array
|
|
3638
|
-
texture_storage_3d
|
|
3639
|
-
`;
|
|
3640
|
-
const stdTypes = `array atomic bool f16 f32 i32
|
|
3641
|
-
mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4
|
|
3642
|
-
mat2x2f mat2x3f mat2x4f mat3x2f mat3x3f mat3x4f
|
|
3643
|
-
mat4x2f mat4x3f mat4x4f
|
|
3644
|
-
mat2x2h mat2x3h mat2x4h mat3x2h mat3x3h mat3x4h
|
|
3645
|
-
mat4x2h mat4x3h mat4x4h
|
|
3646
|
-
u32 vec2 vec3 vec4 ptr
|
|
3647
|
-
vec2i vec3i vec4i vec2u vec3u vec4u
|
|
3648
|
-
vec2f vec3f vec4f vec2h vec3h vec4h
|
|
3649
|
-
${sampledTextureTypes}
|
|
3650
|
-
${multisampledTextureTypes}
|
|
3651
|
-
texture_external
|
|
3652
|
-
${textureStorageTypes}
|
|
3653
|
-
texture_depth_2d texture_depth_2d_array texture_depth_cube
|
|
3654
|
-
texture_depth_cube_array
|
|
3655
|
-
sampler sampler_comparison
|
|
3656
|
-
rgba8unorm rgba8snorm rgba8uint rgba8sint
|
|
3657
|
-
rgba16uint rgba16sint rgba16float
|
|
3658
|
-
r32uint r32sint r32float rg32uint rg32sint rg32float
|
|
3659
|
-
rgba32uint rgba32sint rgba32float
|
|
3660
|
-
bgra8unorm`.split(/\s+/);
|
|
3661
|
-
/** https://www.w3.org/TR/WGSL/#predeclared-enumerants */
|
|
3662
|
-
const stdEnumerants = `read write read_write
|
|
3663
|
-
function private workgroup uniform storage
|
|
3664
|
-
rgba8unorm rgba8snorm rgba8uint rgba8sint
|
|
3665
|
-
rgba16uint rgba16sint rgba16float
|
|
3666
|
-
r32uint r32sint r32float rg32uint rg32sint rg32float
|
|
3667
|
-
rgba32uint rgba32sint rgba32float bgra8unorm`.split(/\s+/);
|
|
3668
|
-
/** return true if the name is for a built in type (not a user struct) */
|
|
3669
|
-
function stdType(name) {
|
|
3670
|
-
return stdTypes.includes(name);
|
|
3671
|
-
}
|
|
3672
|
-
/** return true if the name is for a built in fn (not a user function) */
|
|
3673
|
-
function stdFn(name) {
|
|
3674
|
-
return stdFns.includes(name) || stdType(name);
|
|
3675
|
-
}
|
|
3676
|
-
/** return true if the name is for a built in enumerant */
|
|
3677
|
-
function stdEnumerant(name) {
|
|
3678
|
-
return stdEnumerants.includes(name);
|
|
3679
|
-
}
|
|
3680
|
-
|
|
3681
3680
|
//#endregion
|
|
3682
3681
|
//#region src/BindIdents.ts
|
|
3683
|
-
/** WGSL standard attributes whose params need binding (e.g., @workgroup_size). */
|
|
3684
|
-
const wgslStandardAttributes = new Set([
|
|
3685
|
-
"align",
|
|
3686
|
-
"binding",
|
|
3687
|
-
"blend_src",
|
|
3688
|
-
"compute",
|
|
3689
|
-
"const",
|
|
3690
|
-
"fragment",
|
|
3691
|
-
"group",
|
|
3692
|
-
"id",
|
|
3693
|
-
"invariant",
|
|
3694
|
-
"location",
|
|
3695
|
-
"must_use",
|
|
3696
|
-
"size",
|
|
3697
|
-
"vertex",
|
|
3698
|
-
"workgroup_size"
|
|
3699
|
-
]);
|
|
3700
3682
|
/** Bind ref idents to declarations and mangle global declaration names. */
|
|
3701
3683
|
function bindIdents(params) {
|
|
3702
3684
|
const { rootAst, resolver, virtuals, accumulateUnbound } = params;
|
|
3703
3685
|
const { conditions = {}, mangler = minimalMangle } = params;
|
|
3686
|
+
const { discoveryMode } = params;
|
|
3704
3687
|
const packageName = rootAst.srcModule.modulePath.split("::")[0];
|
|
3705
|
-
const
|
|
3706
|
-
const { globalNames, knownDecls } = initRootDecls(
|
|
3688
|
+
const rootDecls = discoveryMode ? findAllRootDecls(rootAst.rootScope) : findValidRootDecls(rootAst.rootScope, conditions);
|
|
3689
|
+
const { globalNames, knownDecls } = initRootDecls(rootDecls);
|
|
3707
3690
|
const bindContext = {
|
|
3708
3691
|
resolver,
|
|
3709
3692
|
conditions,
|
|
@@ -3714,13 +3697,14 @@ function bindIdents(params) {
|
|
|
3714
3697
|
foundScopes: /* @__PURE__ */ new Set(),
|
|
3715
3698
|
globalNames,
|
|
3716
3699
|
globalStatements: /* @__PURE__ */ new Map(),
|
|
3717
|
-
unbound: accumulateUnbound ? [] : void 0
|
|
3700
|
+
unbound: accumulateUnbound ? [] : void 0,
|
|
3701
|
+
discoveryMode
|
|
3718
3702
|
};
|
|
3719
3703
|
const liveDecls = {
|
|
3720
|
-
decls: new Map(
|
|
3704
|
+
decls: new Map(rootDecls.map((d) => [d.originalName, d])),
|
|
3721
3705
|
parent: null
|
|
3722
3706
|
};
|
|
3723
|
-
const fromRootDecls =
|
|
3707
|
+
const fromRootDecls = rootDecls.flatMap((decl) => processDependentScope(decl, bindContext));
|
|
3724
3708
|
const fromRefs = bindIdentsRecursive(rootAst.rootScope, bindContext, liveDecls);
|
|
3725
3709
|
const newStatements = [...bindContext.globalStatements.values()];
|
|
3726
3710
|
return {
|
|
@@ -3756,10 +3740,11 @@ function* validItems(scope, conditions) {
|
|
|
3756
3740
|
}
|
|
3757
3741
|
/** Find all conditionally valid declarations at the root level. */
|
|
3758
3742
|
function findValidRootDecls(rootScope, conditions) {
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3743
|
+
return collectDecls(validItems(rootScope, conditions));
|
|
3744
|
+
}
|
|
3745
|
+
/** Find all declarations at the root level, ignoring conditions. */
|
|
3746
|
+
function findAllRootDecls(rootScope) {
|
|
3747
|
+
return collectDecls(rootScope.contents);
|
|
3763
3748
|
}
|
|
3764
3749
|
/** Find a public declaration with the given original name. */
|
|
3765
3750
|
function publicDecl(scope, name, conditions) {
|
|
@@ -3785,7 +3770,8 @@ function bindIdentsRecursive(scope, bindContext, liveDecls) {
|
|
|
3785
3770
|
function processScope(scope, bindContext, liveDecls) {
|
|
3786
3771
|
const newGlobals = [];
|
|
3787
3772
|
const newFromChildren = [];
|
|
3788
|
-
|
|
3773
|
+
const items = bindContext.discoveryMode ? scope.contents : validItems(scope, bindContext.conditions);
|
|
3774
|
+
for (const child of items) if (child.kind === "decl") liveDecls.decls.set(child.originalName, child);
|
|
3789
3775
|
else if (child.kind === "ref") {
|
|
3790
3776
|
const newDecl = handleRef(child, liveDecls, bindContext);
|
|
3791
3777
|
if (newDecl) newGlobals.push(newDecl);
|
|
@@ -3811,25 +3797,26 @@ function processDependentScope(decl, ctx) {
|
|
|
3811
3797
|
* Mutates to mangle declarations and mark std references.
|
|
3812
3798
|
* @return found declaration, or undefined if already processed
|
|
3813
3799
|
*/
|
|
3814
|
-
function handleRef(ident
|
|
3815
|
-
if (ident
|
|
3816
|
-
if (ident
|
|
3817
|
-
if (ident
|
|
3818
|
-
const foundDecl = findDeclInModule(ident
|
|
3800
|
+
function handleRef(ident, liveDecls, bindContext) {
|
|
3801
|
+
if (ident.refersTo || ident.std) return;
|
|
3802
|
+
if (ident.conditionRef) return;
|
|
3803
|
+
if (ident.attrParam && !wgslStandardAttributes.has(ident.attrParam)) return;
|
|
3804
|
+
const foundDecl = findDeclInModule(ident, liveDecls) ?? findQualifiedImport(ident, bindContext);
|
|
3819
3805
|
if (foundDecl) {
|
|
3820
|
-
ident
|
|
3821
|
-
return handleNewDecl(ident
|
|
3806
|
+
ident.refersTo = foundDecl.decl;
|
|
3807
|
+
return handleNewDecl(ident, foundDecl, bindContext);
|
|
3822
3808
|
}
|
|
3823
|
-
if (stdWgsl(ident
|
|
3824
|
-
ident
|
|
3809
|
+
if (stdWgsl(ident.originalName)) {
|
|
3810
|
+
ident.std = true;
|
|
3825
3811
|
return;
|
|
3826
3812
|
}
|
|
3827
|
-
if (!bindContext.unbound) failIdent(ident
|
|
3813
|
+
if (!bindContext.unbound) failIdent(ident, `unresolved identifier '${ident.originalName}'`);
|
|
3828
3814
|
}
|
|
3815
|
+
/** Follow new global declarations into their dependent scopes. */
|
|
3829
3816
|
function handleDecls(newGlobals, bindContext) {
|
|
3830
3817
|
return newGlobals.flatMap((decl) => processDependentScope(decl, bindContext));
|
|
3831
3818
|
}
|
|
3832
|
-
/** If found declaration is new, mangle its name.
|
|
3819
|
+
/** If found declaration is new, mangle its name. @return the decl if it's global. */
|
|
3833
3820
|
function handleNewDecl(refIdent, foundDecl, ctx) {
|
|
3834
3821
|
const { decl, moduleAst } = foundDecl;
|
|
3835
3822
|
const { knownDecls, globalNames, mangler, globalStatements } = ctx;
|
|
@@ -3845,18 +3832,19 @@ function handleNewDecl(refIdent, foundDecl, ctx) {
|
|
|
3845
3832
|
return decl;
|
|
3846
3833
|
}
|
|
3847
3834
|
/** Search current scope and parent scopes for a matching declaration. */
|
|
3848
|
-
function findDeclInModule(ident
|
|
3849
|
-
const found = liveDecls.decls.get(ident
|
|
3835
|
+
function findDeclInModule(ident, liveDecls) {
|
|
3836
|
+
const found = liveDecls.decls.get(ident.originalName);
|
|
3850
3837
|
if (found) return {
|
|
3851
3838
|
decl: found,
|
|
3852
|
-
moduleAst: ident
|
|
3839
|
+
moduleAst: ident.ast
|
|
3853
3840
|
};
|
|
3854
|
-
if (liveDecls.parent) return findDeclInModule(ident
|
|
3841
|
+
if (liveDecls.parent) return findDeclInModule(ident, liveDecls.parent);
|
|
3855
3842
|
}
|
|
3856
3843
|
/** Match a ref ident to a declaration in another module via import or qualified ident. */
|
|
3857
3844
|
function findQualifiedImport(refIdent, ctx) {
|
|
3858
|
-
const { conditions, unbound } = ctx;
|
|
3859
|
-
const
|
|
3845
|
+
const { conditions, unbound, discoveryMode } = ctx;
|
|
3846
|
+
const conds = discoveryMode ? void 0 : conditions;
|
|
3847
|
+
const flatImps = flatImports(refIdent.ast, conds);
|
|
3860
3848
|
const identParts = refIdent.originalName.split("::");
|
|
3861
3849
|
const pathParts = matchingImport(identParts, flatImps) ?? qualifiedIdent(identParts);
|
|
3862
3850
|
if (!pathParts) {
|
|
@@ -3910,7 +3898,7 @@ function virtualModule(moduleName, ctx) {
|
|
|
3910
3898
|
/** Get cached valid root declarations, computing on first access. */
|
|
3911
3899
|
function getValidRootDecls(rootScope, conditions) {
|
|
3912
3900
|
const lexScope = rootScope;
|
|
3913
|
-
|
|
3901
|
+
lexScope._validRootDecls ??= findValidRootDecls(rootScope, conditions);
|
|
3914
3902
|
return lexScope._validRootDecls;
|
|
3915
3903
|
}
|
|
3916
3904
|
/** Given a global declIdent, return the liveDecls for its root scope. */
|
|
@@ -3939,13 +3927,167 @@ function setMangledName(proposedName, decl, globalNames, srcModule, mangler) {
|
|
|
3939
3927
|
function stdWgsl(name) {
|
|
3940
3928
|
return stdType(name) || stdFn(name) || stdEnumerant(name);
|
|
3941
3929
|
}
|
|
3930
|
+
/** @return identParts if it's a qualified path (has ::). */
|
|
3942
3931
|
function qualifiedIdent(identParts) {
|
|
3943
3932
|
if (identParts.length > 1) return identParts;
|
|
3944
3933
|
}
|
|
3945
|
-
/** Collect all declarations
|
|
3946
|
-
function collectDecls(
|
|
3947
|
-
|
|
3948
|
-
|
|
3934
|
+
/** Collect all declarations from scope items, recursing into partial scopes. */
|
|
3935
|
+
function collectDecls(items) {
|
|
3936
|
+
return [...items].flatMap((item) => {
|
|
3937
|
+
const { kind } = item;
|
|
3938
|
+
if (kind === "decl") return [item];
|
|
3939
|
+
if (kind === "partial") return collectDecls(item.contents);
|
|
3940
|
+
return [];
|
|
3941
|
+
});
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
//#endregion
|
|
3945
|
+
//#region src/PathUtil.ts
|
|
3946
|
+
/** simplistic path manipulation utilities */
|
|
3947
|
+
/** return path with ./ and foo/.. elements removed */
|
|
3948
|
+
function normalize(path) {
|
|
3949
|
+
const noDots = path.split("/").filter((s) => s !== ".");
|
|
3950
|
+
const noDbl = [];
|
|
3951
|
+
noDots.forEach((s) => {
|
|
3952
|
+
if (s !== "") if (s === ".." && noDbl.length && noDbl[noDbl.length - 1] !== "..") noDbl.pop();
|
|
3953
|
+
else noDbl.push(s);
|
|
3954
|
+
});
|
|
3955
|
+
return noDbl.join("/");
|
|
3956
|
+
}
|
|
3957
|
+
/** return path w/o a suffix.
|
|
3958
|
+
* e.g. /foo/bar.wgsl => /foo/bar */
|
|
3959
|
+
function noSuffix(path) {
|
|
3960
|
+
const lastSlash = path.lastIndexOf("/");
|
|
3961
|
+
const lastStart = lastSlash === -1 ? 0 : lastSlash + 1;
|
|
3962
|
+
const suffix = path.indexOf(".", lastStart);
|
|
3963
|
+
const suffixStart = suffix === -1 ? path.length : suffix;
|
|
3964
|
+
return path.slice(0, suffixStart);
|
|
3965
|
+
}
|
|
3966
|
+
|
|
3967
|
+
//#endregion
|
|
3968
|
+
//#region src/ModuleResolver.ts
|
|
3969
|
+
const libRegex = /^lib\.w[eg]sl$/i;
|
|
3970
|
+
/** Module resolver for in-memory source records. Lazy by default. */
|
|
3971
|
+
var RecordResolver = class {
|
|
3972
|
+
astCache = /* @__PURE__ */ new Map();
|
|
3973
|
+
sources;
|
|
3974
|
+
packageName;
|
|
3975
|
+
debugWeslRoot;
|
|
3976
|
+
constructor(sources, options = {}) {
|
|
3977
|
+
const { packageName = "package", debugWeslRoot } = options;
|
|
3978
|
+
this.sources = sources;
|
|
3979
|
+
this.packageName = packageName;
|
|
3980
|
+
this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
|
|
3981
|
+
}
|
|
3982
|
+
resolveModule(modulePath) {
|
|
3983
|
+
const cached = this.astCache.get(modulePath);
|
|
3984
|
+
if (cached) return cached;
|
|
3985
|
+
const source = this.findSource(modulePath);
|
|
3986
|
+
if (source === void 0) return void 0;
|
|
3987
|
+
const ast = parseSrcModule({
|
|
3988
|
+
modulePath,
|
|
3989
|
+
debugFilePath: this.modulePathToDebugPath(modulePath),
|
|
3990
|
+
src: source
|
|
3991
|
+
});
|
|
3992
|
+
this.astCache.set(modulePath, ast);
|
|
3993
|
+
return ast;
|
|
3994
|
+
}
|
|
3995
|
+
findSource(modulePath) {
|
|
3996
|
+
if (this.sources[modulePath] !== void 0) return this.sources[modulePath];
|
|
3997
|
+
const filePath = this.moduleToFilePath(modulePath);
|
|
3998
|
+
if (filePath === void 0) return void 0;
|
|
3999
|
+
return findInVariants(this.sources, filePath);
|
|
4000
|
+
}
|
|
4001
|
+
/** Convert module path to file path, or undefined if not local. */
|
|
4002
|
+
moduleToFilePath(modulePath) {
|
|
4003
|
+
return moduleToRelativePath(modulePath, this.packageName);
|
|
4004
|
+
}
|
|
4005
|
+
modulePathToDebugPath(modulePath) {
|
|
4006
|
+
const filePath = this.moduleToFilePath(modulePath) ?? modulePath;
|
|
4007
|
+
return this.debugWeslRoot + filePath + ".wesl";
|
|
4008
|
+
}
|
|
4009
|
+
/** Parse all modules and return entries. */
|
|
4010
|
+
allModules() {
|
|
4011
|
+
for (const filePath of Object.keys(this.sources)) {
|
|
4012
|
+
const treatLibAsRoot = this.packageName !== "package";
|
|
4013
|
+
const modulePath = fileToModulePath(filePath, this.packageName, treatLibAsRoot);
|
|
4014
|
+
this.resolveModule(modulePath);
|
|
4015
|
+
}
|
|
4016
|
+
return this.astCache.entries();
|
|
4017
|
+
}
|
|
4018
|
+
};
|
|
4019
|
+
/** Composite resolver that tries each resolver in order until one succeeds. */
|
|
4020
|
+
var CompositeResolver = class {
|
|
4021
|
+
resolvers;
|
|
4022
|
+
constructor(resolvers) {
|
|
4023
|
+
this.resolvers = resolvers;
|
|
4024
|
+
}
|
|
4025
|
+
resolveModule(modulePath) {
|
|
4026
|
+
for (const resolver of this.resolvers) {
|
|
4027
|
+
const ast = resolver.resolveModule(modulePath);
|
|
4028
|
+
if (ast) return ast;
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
};
|
|
4032
|
+
/** Lazy resolver for WeslBundle library modules. */
|
|
4033
|
+
var BundleResolver = class {
|
|
4034
|
+
astCache = /* @__PURE__ */ new Map();
|
|
4035
|
+
sources;
|
|
4036
|
+
packageName;
|
|
4037
|
+
debugWeslRoot;
|
|
4038
|
+
constructor(bundle, debugWeslRoot) {
|
|
4039
|
+
this.sources = bundle.modules;
|
|
4040
|
+
this.packageName = bundle.name;
|
|
4041
|
+
this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
|
|
4042
|
+
}
|
|
4043
|
+
resolveModule(modulePath) {
|
|
4044
|
+
const pkgPrefix = this.packageName + "::";
|
|
4045
|
+
if (modulePath !== this.packageName && !modulePath.startsWith(pkgPrefix)) return;
|
|
4046
|
+
const cached = this.astCache.get(modulePath);
|
|
4047
|
+
if (cached) return cached;
|
|
4048
|
+
const source = this.findSource(modulePath);
|
|
4049
|
+
if (!source) return void 0;
|
|
4050
|
+
const ast = parseSrcModule({
|
|
4051
|
+
modulePath,
|
|
4052
|
+
debugFilePath: this.modulePathToDebugPath(modulePath),
|
|
4053
|
+
src: source
|
|
4054
|
+
});
|
|
4055
|
+
this.astCache.set(modulePath, ast);
|
|
4056
|
+
return ast;
|
|
4057
|
+
}
|
|
4058
|
+
findSource(modulePath) {
|
|
4059
|
+
const filePath = this.moduleToFilePath(modulePath);
|
|
4060
|
+
if (modulePath === this.packageName) {
|
|
4061
|
+
const libSrc = findInVariants(this.sources, "lib", ["wesl", "wgsl"]);
|
|
4062
|
+
if (libSrc) return libSrc;
|
|
4063
|
+
}
|
|
4064
|
+
return findInVariants(this.sources, filePath);
|
|
4065
|
+
}
|
|
4066
|
+
moduleToFilePath(modulePath) {
|
|
4067
|
+
return moduleToRelativePath(modulePath, this.packageName) ?? modulePath;
|
|
4068
|
+
}
|
|
4069
|
+
modulePathToDebugPath(modulePath) {
|
|
4070
|
+
const filePath = this.moduleToFilePath(modulePath);
|
|
4071
|
+
return this.debugWeslRoot + this.packageName + "/" + filePath + ".wesl";
|
|
4072
|
+
}
|
|
4073
|
+
};
|
|
4074
|
+
/** Convert file path to module path (e.g., "foo/bar.wesl" to "package::foo::bar"). */
|
|
4075
|
+
function fileToModulePath(filePath, packageName, treatLibAsRoot) {
|
|
4076
|
+
if (filePath.includes("::")) return filePath;
|
|
4077
|
+
if (treatLibAsRoot && libRegex.test(filePath)) return packageName;
|
|
4078
|
+
const moduleSuffix = noSuffix(normalize(filePath)).replaceAll("/", "::");
|
|
4079
|
+
return packageName + "::" + moduleSuffix;
|
|
4080
|
+
}
|
|
4081
|
+
/** Try path variants with/without ./ prefix and extension suffixes. */
|
|
4082
|
+
function findInVariants(sources, basePath, extensions = ["wesl", "wgsl"]) {
|
|
4083
|
+
for (const prefix of ["", "./"]) {
|
|
4084
|
+
const path = prefix + basePath;
|
|
4085
|
+
if (sources[path] !== void 0) return sources[path];
|
|
4086
|
+
for (const ext of extensions) {
|
|
4087
|
+
const withExt = `${path}.${ext}`;
|
|
4088
|
+
if (sources[withExt] !== void 0) return sources[withExt];
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
3949
4091
|
}
|
|
3950
4092
|
|
|
3951
4093
|
//#endregion
|
|
@@ -3975,21 +4117,57 @@ function findUnboundRefs(resolver) {
|
|
|
3975
4117
|
mangler: minimalMangle,
|
|
3976
4118
|
packageName: "package",
|
|
3977
4119
|
unbound: [],
|
|
3978
|
-
dontFollowDecls: true
|
|
4120
|
+
dontFollowDecls: true,
|
|
4121
|
+
discoveryMode: true
|
|
3979
4122
|
};
|
|
3980
4123
|
for (const [, ast] of resolver.allModules()) {
|
|
3981
|
-
const rootDecls =
|
|
4124
|
+
const rootDecls = findAllRootDecls(ast.rootScope);
|
|
3982
4125
|
const liveDecls = {
|
|
3983
4126
|
decls: new Map(rootDecls.map((d) => [d.originalName, d])),
|
|
3984
4127
|
parent: null
|
|
3985
4128
|
};
|
|
3986
|
-
filterMap(rootDecls, (decl) => decl.dependentScope)
|
|
3987
|
-
bindIdentsRecursive(s, bindContext, makeLiveDecls(liveDecls));
|
|
3988
|
-
});
|
|
4129
|
+
for (const s of filterMap(rootDecls, (decl) => decl.dependentScope)) bindIdentsRecursive(s, bindContext, makeLiveDecls(liveDecls));
|
|
3989
4130
|
bindIdentsRecursive(ast.rootScope, bindContext, liveDecls);
|
|
3990
4131
|
}
|
|
3991
4132
|
return bindContext.unbound;
|
|
3992
4133
|
}
|
|
4134
|
+
/** Thin decorator that records which modules were resolved. */
|
|
4135
|
+
var TrackingResolver = class {
|
|
4136
|
+
visited = /* @__PURE__ */ new Set();
|
|
4137
|
+
#inner;
|
|
4138
|
+
constructor(inner) {
|
|
4139
|
+
this.#inner = inner;
|
|
4140
|
+
}
|
|
4141
|
+
resolveModule(modulePath) {
|
|
4142
|
+
const ast = this.#inner.resolveModule(modulePath);
|
|
4143
|
+
if (ast) this.visited.add(modulePath);
|
|
4144
|
+
return ast;
|
|
4145
|
+
}
|
|
4146
|
+
};
|
|
4147
|
+
/**
|
|
4148
|
+
* Discover reachable modules and unbound external refs from a single root.
|
|
4149
|
+
*
|
|
4150
|
+
* Traces the import graph from `rootModuleName`, returning only the reachable
|
|
4151
|
+
* local modules in `weslSrc` and unresolved external references in `unbound`.
|
|
4152
|
+
*/
|
|
4153
|
+
function discoverModules(weslSrc, resolver, rootModuleName, packageName = "package") {
|
|
4154
|
+
const tracking = new TrackingResolver(resolver);
|
|
4155
|
+
const rootAst = tracking.resolveModule(rootModuleName);
|
|
4156
|
+
if (!rootAst) throw new Error(`root module not found: '${rootModuleName}'`);
|
|
4157
|
+
const result = bindIdents({
|
|
4158
|
+
rootAst,
|
|
4159
|
+
resolver: tracking,
|
|
4160
|
+
accumulateUnbound: true,
|
|
4161
|
+
discoveryMode: true
|
|
4162
|
+
});
|
|
4163
|
+
const moduleToKey = new Map(Object.keys(weslSrc).map((key) => [fileToModulePath(key, packageName, false), key]));
|
|
4164
|
+
const reachable = [...tracking.visited].map((m) => moduleToKey.get(m)).filter((key) => key !== void 0).map((key) => [key, weslSrc[key]]);
|
|
4165
|
+
const unbound = (result.unbound ?? []).map((ref) => ref.path);
|
|
4166
|
+
return {
|
|
4167
|
+
weslSrc: Object.fromEntries(reachable),
|
|
4168
|
+
unbound
|
|
4169
|
+
};
|
|
4170
|
+
}
|
|
3993
4171
|
|
|
3994
4172
|
//#endregion
|
|
3995
4173
|
//#region src/discovery/PackageNameUtils.ts
|
|
@@ -4160,155 +4338,6 @@ function compilationInfoToErrorMessage(compilationInfo, shaderModule) {
|
|
|
4160
4338
|
return result;
|
|
4161
4339
|
}
|
|
4162
4340
|
|
|
4163
|
-
//#endregion
|
|
4164
|
-
//#region src/PathUtil.ts
|
|
4165
|
-
/** simplistic path manipulation utilities */
|
|
4166
|
-
/** return path with ./ and foo/.. elements removed */
|
|
4167
|
-
function normalize(path) {
|
|
4168
|
-
const noDots = path.split("/").filter((s) => s !== ".");
|
|
4169
|
-
const noDbl = [];
|
|
4170
|
-
noDots.forEach((s) => {
|
|
4171
|
-
if (s !== "") if (s === ".." && noDbl.length && noDbl[noDbl.length - 1] !== "..") noDbl.pop();
|
|
4172
|
-
else noDbl.push(s);
|
|
4173
|
-
});
|
|
4174
|
-
return noDbl.join("/");
|
|
4175
|
-
}
|
|
4176
|
-
/** return path w/o a suffix.
|
|
4177
|
-
* e.g. /foo/bar.wgsl => /foo/bar */
|
|
4178
|
-
function noSuffix(path) {
|
|
4179
|
-
const lastSlash = path.lastIndexOf("/");
|
|
4180
|
-
const lastStart = lastSlash === -1 ? 0 : lastSlash + 1;
|
|
4181
|
-
const suffix = path.indexOf(".", lastStart);
|
|
4182
|
-
const suffixStart = suffix === -1 ? path.length : suffix;
|
|
4183
|
-
return path.slice(0, suffixStart);
|
|
4184
|
-
}
|
|
4185
|
-
|
|
4186
|
-
//#endregion
|
|
4187
|
-
//#region src/ModuleResolver.ts
|
|
4188
|
-
const libRegex = /^lib\.w[eg]sl$/i;
|
|
4189
|
-
/** Module resolver for in-memory source records. Lazy by default. */
|
|
4190
|
-
var RecordResolver = class {
|
|
4191
|
-
astCache = /* @__PURE__ */ new Map();
|
|
4192
|
-
sources;
|
|
4193
|
-
packageName;
|
|
4194
|
-
debugWeslRoot;
|
|
4195
|
-
constructor(sources, options = {}) {
|
|
4196
|
-
const { packageName = "package", debugWeslRoot } = options;
|
|
4197
|
-
this.sources = sources;
|
|
4198
|
-
this.packageName = packageName;
|
|
4199
|
-
this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
|
|
4200
|
-
}
|
|
4201
|
-
resolveModule(modulePath) {
|
|
4202
|
-
const cached = this.astCache.get(modulePath);
|
|
4203
|
-
if (cached) return cached;
|
|
4204
|
-
const source = this.findSource(modulePath);
|
|
4205
|
-
if (source === void 0) return void 0;
|
|
4206
|
-
const ast = parseSrcModule({
|
|
4207
|
-
modulePath,
|
|
4208
|
-
debugFilePath: this.modulePathToDebugPath(modulePath),
|
|
4209
|
-
src: source
|
|
4210
|
-
});
|
|
4211
|
-
this.astCache.set(modulePath, ast);
|
|
4212
|
-
return ast;
|
|
4213
|
-
}
|
|
4214
|
-
findSource(modulePath) {
|
|
4215
|
-
if (this.sources[modulePath] !== void 0) return this.sources[modulePath];
|
|
4216
|
-
const filePath = this.moduleToFilePath(modulePath);
|
|
4217
|
-
if (filePath === void 0) return void 0;
|
|
4218
|
-
return findInVariants(this.sources, filePath);
|
|
4219
|
-
}
|
|
4220
|
-
/** Convert module path to file path, or undefined if not local. */
|
|
4221
|
-
moduleToFilePath(modulePath) {
|
|
4222
|
-
return moduleToRelativePath(modulePath, this.packageName);
|
|
4223
|
-
}
|
|
4224
|
-
modulePathToDebugPath(modulePath) {
|
|
4225
|
-
const filePath = this.moduleToFilePath(modulePath) ?? modulePath;
|
|
4226
|
-
return this.debugWeslRoot + filePath + ".wesl";
|
|
4227
|
-
}
|
|
4228
|
-
/** Parse all modules and return entries. */
|
|
4229
|
-
allModules() {
|
|
4230
|
-
for (const filePath of Object.keys(this.sources)) {
|
|
4231
|
-
const treatLibAsRoot = this.packageName !== "package";
|
|
4232
|
-
const modulePath = fileToModulePath(filePath, this.packageName, treatLibAsRoot);
|
|
4233
|
-
this.resolveModule(modulePath);
|
|
4234
|
-
}
|
|
4235
|
-
return this.astCache.entries();
|
|
4236
|
-
}
|
|
4237
|
-
};
|
|
4238
|
-
/** Composite resolver that tries each resolver in order until one succeeds. */
|
|
4239
|
-
var CompositeResolver = class {
|
|
4240
|
-
resolvers;
|
|
4241
|
-
constructor(resolvers) {
|
|
4242
|
-
this.resolvers = resolvers;
|
|
4243
|
-
}
|
|
4244
|
-
resolveModule(modulePath) {
|
|
4245
|
-
for (const resolver of this.resolvers) {
|
|
4246
|
-
const ast = resolver.resolveModule(modulePath);
|
|
4247
|
-
if (ast) return ast;
|
|
4248
|
-
}
|
|
4249
|
-
}
|
|
4250
|
-
};
|
|
4251
|
-
/** Lazy resolver for WeslBundle library modules. */
|
|
4252
|
-
var BundleResolver = class {
|
|
4253
|
-
astCache = /* @__PURE__ */ new Map();
|
|
4254
|
-
sources;
|
|
4255
|
-
packageName;
|
|
4256
|
-
debugWeslRoot;
|
|
4257
|
-
constructor(bundle, debugWeslRoot) {
|
|
4258
|
-
this.sources = bundle.modules;
|
|
4259
|
-
this.packageName = bundle.name;
|
|
4260
|
-
this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
|
|
4261
|
-
}
|
|
4262
|
-
resolveModule(modulePath) {
|
|
4263
|
-
const pkgPrefix = this.packageName + "::";
|
|
4264
|
-
if (modulePath !== this.packageName && !modulePath.startsWith(pkgPrefix)) return;
|
|
4265
|
-
const cached = this.astCache.get(modulePath);
|
|
4266
|
-
if (cached) return cached;
|
|
4267
|
-
const source = this.findSource(modulePath);
|
|
4268
|
-
if (!source) return void 0;
|
|
4269
|
-
const ast = parseSrcModule({
|
|
4270
|
-
modulePath,
|
|
4271
|
-
debugFilePath: this.modulePathToDebugPath(modulePath),
|
|
4272
|
-
src: source
|
|
4273
|
-
});
|
|
4274
|
-
this.astCache.set(modulePath, ast);
|
|
4275
|
-
return ast;
|
|
4276
|
-
}
|
|
4277
|
-
findSource(modulePath) {
|
|
4278
|
-
const filePath = this.moduleToFilePath(modulePath);
|
|
4279
|
-
if (modulePath === this.packageName) {
|
|
4280
|
-
const libSrc = findInVariants(this.sources, "lib", ["wesl", "wgsl"]);
|
|
4281
|
-
if (libSrc) return libSrc;
|
|
4282
|
-
}
|
|
4283
|
-
return findInVariants(this.sources, filePath);
|
|
4284
|
-
}
|
|
4285
|
-
moduleToFilePath(modulePath) {
|
|
4286
|
-
return moduleToRelativePath(modulePath, this.packageName) ?? modulePath;
|
|
4287
|
-
}
|
|
4288
|
-
modulePathToDebugPath(modulePath) {
|
|
4289
|
-
const filePath = this.moduleToFilePath(modulePath);
|
|
4290
|
-
return this.debugWeslRoot + this.packageName + "/" + filePath + ".wesl";
|
|
4291
|
-
}
|
|
4292
|
-
};
|
|
4293
|
-
/** Convert file path to module path (e.g., "foo/bar.wesl" to "package::foo::bar"). */
|
|
4294
|
-
function fileToModulePath(filePath, packageName, treatLibAsRoot) {
|
|
4295
|
-
if (filePath.includes("::")) return filePath;
|
|
4296
|
-
if (treatLibAsRoot && libRegex.test(filePath)) return packageName;
|
|
4297
|
-
const moduleSuffix = noSuffix(normalize(filePath)).replaceAll("/", "::");
|
|
4298
|
-
return packageName + "::" + moduleSuffix;
|
|
4299
|
-
}
|
|
4300
|
-
/** Try path variants with/without ./ prefix and extension suffixes. */
|
|
4301
|
-
function findInVariants(sources, basePath, extensions = ["wesl", "wgsl"]) {
|
|
4302
|
-
for (const prefix of ["", "./"]) {
|
|
4303
|
-
const path = prefix + basePath;
|
|
4304
|
-
if (sources[path] !== void 0) return sources[path];
|
|
4305
|
-
for (const ext of extensions) {
|
|
4306
|
-
const withExt = `${path}.${ext}`;
|
|
4307
|
-
if (sources[withExt] !== void 0) return sources[withExt];
|
|
4308
|
-
}
|
|
4309
|
-
}
|
|
4310
|
-
}
|
|
4311
|
-
|
|
4312
4341
|
//#endregion
|
|
4313
4342
|
//#region src/SrcMap.ts
|
|
4314
4343
|
/** map text ranges in multiple src texts to a single dest text */
|
|
@@ -4857,8 +4886,8 @@ function refersToBindingStruct(memberRef) {
|
|
|
4857
4886
|
};
|
|
4858
4887
|
}
|
|
4859
4888
|
/** If this identifier ultimately refers to a struct type, return the struct declaration */
|
|
4860
|
-
function traceToStruct(ident
|
|
4861
|
-
const declElem = findDecl(ident
|
|
4889
|
+
function traceToStruct(ident) {
|
|
4890
|
+
const declElem = findDecl(ident).declElem;
|
|
4862
4891
|
if (declElem && declElem.kind === "param") {
|
|
4863
4892
|
const name = declElem.name.typeRef?.name;
|
|
4864
4893
|
if (typeof name !== "string") {
|
|
@@ -4963,4 +4992,4 @@ function makeWeslDevice(device) {
|
|
|
4963
4992
|
}
|
|
4964
4993
|
|
|
4965
4994
|
//#endregion
|
|
4966
|
-
export { BundleResolver, CompositeResolver, LinkedWesl, ParseError, RecordResolver, SrcMap, SrcMapBuilder, WeslParseError, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, childIdent, childScope, containsScope, debug, debugContentsToString, emptyScope, errorHighlight, fileToModulePath, filterMap, findMap, findRefsToBindingStructs, findUnboundIdents, findUnboundRefs, findValidRootDecls, flatImports, groupBy, grouped, identToString, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, log, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, modulePartsToRelativePath, moduleToRelativePath, multiKeySet, multisampledTextureTypes, nextIdentId, noSuffix, normalize, normalizeDebugRoot, normalizeModuleName, npmNameVariations, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, resolveModulePath, sampledTextureTypes, sanitizePackageName, scan, scopeToString, scopeToStringLong, srcLog, stdEnumerant, stdEnumerants, stdFn, stdFns, stdType, stdTypes, textureStorageTypes, transformBindingReference, transformBindingStruct, underscoreMangle, validation, withLoggerAsync };
|
|
4995
|
+
export { BundleResolver, CompositeResolver, LinkedWesl, ParseError, RecordResolver, SrcMap, SrcMapBuilder, TrackingResolver, WeslParseError, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, childIdent, childScope, containsScope, debug, debugContentsToString, discoverModules, emptyScope, errorHighlight, fileToModulePath, filterMap, filterValidElements, findAllRootDecls, findMap, findRefsToBindingStructs, findUnboundIdents, findUnboundRefs, findValidRootDecls, flatImports, groupBy, grouped, identToString, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, log, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, modulePartsToRelativePath, moduleToRelativePath, multiKeySet, multisampledTextureTypes, nextIdentId, noSuffix, normalize, normalizeDebugRoot, normalizeModuleName, npmNameVariations, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, resolveModulePath, sampledTextureTypes, sanitizePackageName, scan, scopeToString, scopeToStringLong, srcLog, stdEnumerant, stdEnumerants, stdFn, stdFns, stdType, stdTypes, textureStorageTypes, transformBindingReference, transformBindingStruct, underscoreMangle, validation, wgslStandardAttributes, withLoggerAsync };
|