wesl 0.7.25 → 0.7.26
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 +17 -24
- package/dist/index.js +23 -21
- package/package.json +1 -1
- package/src/BindIdents.ts +31 -51
- package/src/Linker.ts +27 -25
- package/src/discovery/FindUnboundIdents.ts +1 -0
package/dist/index.d.ts
CHANGED
|
@@ -889,8 +889,14 @@ interface LinkParams {
|
|
|
889
889
|
}
|
|
890
890
|
/** Project config for web components and tools. */
|
|
891
891
|
type WeslProject = Pick<LinkParams, "weslSrc" | "rootModuleName" | "conditions" | "constants" | "libs" | "packageName">;
|
|
892
|
-
/**
|
|
893
|
-
|
|
892
|
+
/** Context passed to virtual library generators. */
|
|
893
|
+
interface VirtualLibContext {
|
|
894
|
+
conditions: Conditions;
|
|
895
|
+
rootModulePath: string;
|
|
896
|
+
packageName: string;
|
|
897
|
+
}
|
|
898
|
+
/** Generate a virtual WESL module. */
|
|
899
|
+
type VirtualLibraryFn = (ctx: VirtualLibContext) => string;
|
|
894
900
|
/**
|
|
895
901
|
* Link a set of WESL source modules (typically the text from .wesl files) into a single WGSL string.
|
|
896
902
|
* Linking starts with a specified 'root' source module, and recursively incorporates code
|
|
@@ -927,23 +933,12 @@ declare function normalizeModuleName(name: string): string;
|
|
|
927
933
|
//#endregion
|
|
928
934
|
//#region src/BindIdents.d.ts
|
|
929
935
|
/**
|
|
930
|
-
* BindIdents pass:
|
|
931
|
-
*
|
|
932
|
-
* Goals:
|
|
933
|
-
* - Link reference idents to declaration idents
|
|
934
|
-
* - Collect used declarations (to emit in link)
|
|
935
|
-
* - Create mangled names for globals to avoid conflicts
|
|
936
|
+
* BindIdents pass: depth-first walk of the scope tree (not syntax tree),
|
|
937
|
+
* linking ref idents to declarations and mangling global names.
|
|
936
938
|
*
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
*
|
|
940
|
-
* - If no local match: check import statements for external matches
|
|
941
|
-
* - For found global decls: mangle name to be unique, collect for emission
|
|
942
|
-
*
|
|
943
|
-
* LiveDecls: tracks visible declarations at the current position, with parent links.
|
|
944
|
-
*
|
|
945
|
-
* @if/@else: respects conditional compilation by tracking @else validity state,
|
|
946
|
-
* mirroring the emission phase's filterValidElements but on scopes.
|
|
939
|
+
* For each ref: search current scope upward, then check imports for external matches.
|
|
940
|
+
* LiveDecls tracks visible declarations with parent links.
|
|
941
|
+
* @if/@else: mirrors filterValidElements but on scopes.
|
|
947
942
|
*/
|
|
948
943
|
/** Results returned from binding pass. */
|
|
949
944
|
interface BindResults {
|
|
@@ -1014,6 +1009,8 @@ interface BindContext {
|
|
|
1014
1009
|
virtuals?: VirtualLibrarySet;
|
|
1015
1010
|
/** Host package name for resolving package:: in virtual modules. */
|
|
1016
1011
|
packageName: string;
|
|
1012
|
+
/** Root module path (e.g., "package::main"). */
|
|
1013
|
+
rootModulePath: string;
|
|
1017
1014
|
/** Unbound identifiers if accumulateUnbound is true. */
|
|
1018
1015
|
unbound?: UnboundRef[];
|
|
1019
1016
|
/** Don't follow references from declarations (for library dependency detection). */
|
|
@@ -1021,11 +1018,7 @@ interface BindContext {
|
|
|
1021
1018
|
/** Visit all conditional branches (for dependency discovery). */
|
|
1022
1019
|
discoveryMode?: boolean;
|
|
1023
1020
|
}
|
|
1024
|
-
/**
|
|
1025
|
-
* Recursively bind references to declarations in this scope and child scopes.
|
|
1026
|
-
* Tracks @else state to ensure filtered @else blocks don't pull in unused declarations.
|
|
1027
|
-
* @return new declarations found
|
|
1028
|
-
*/
|
|
1021
|
+
/** Recursively bind refs to decls in this scope and children. @return new declarations found */
|
|
1029
1022
|
declare function bindIdentsRecursive(scope: Scope, bindContext: BindContext, liveDecls: LiveDecls): DeclIdent[];
|
|
1030
1023
|
//#endregion
|
|
1031
1024
|
//#region src/Conditions.d.ts
|
|
@@ -1284,4 +1277,4 @@ declare function offsetToLineNumber(offset: number, text: string): [lineNum: num
|
|
|
1284
1277
|
*/
|
|
1285
1278
|
declare function errorHighlight(source: string, span: Span): [string, string];
|
|
1286
1279
|
//#endregion
|
|
1287
|
-
export { AbstractElem, AbstractElemBase, AliasElem, Attribute, AttributeElem, BatchModuleResolver, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST, BindingStructElem, BlockStatement, BoundAndTransformed, BuiltinAttribute, BundleResolver, ComponentExpression, ComponentMemberExpression, CompositeResolver, ConditionalAttribute, Conditions, ConstAssertElem, ConstElem, ContainerElem, ContinuingElem, DeclIdent, DeclIdentElem, DeclarationElem, DiagnosticAttribute, DiagnosticDirective, DiagnosticRule, DirectiveElem, DirectiveVariant, ElemKindMap, ElemWithAttributes, ElemWithContentsBase, ElifAttribute, ElseAttribute, EmittableElem, EnableDirective, ExpressionElem, ExtendedGPUValidationError, FnElem, FnParamElem, FunctionCallExpression, GlobalDeclarationElem, GlobalVarElem, GrammarElem, HasAttributes, Ident, IfAttribute, ImportCollection, ImportElem, ImportItem, ImportSegment, ImportStatement, InterpolateAttribute, LetElem, LexicalScope, LinkConfig, LinkParams, LinkRegistryParams, LinkedWesl, LinkerTransform, Literal, LiveDecls, ManglerFn, ModuleElem, ModuleResolver, NameElem, OpenElem, OverrideElem, ParenthesizedExpression, ParseError, type ParseOptions, PartialScope, RecordResolver, RecordResolverOptions, RefIdent, RefIdentElem, RequiresDirective, Scope, ScopeItem, SimpleMemberRef, Span, SrcMap, SrcMapBuilder, SrcMapEntry, SrcModule, SrcPosition, SrcWithPath, StableState, StandardAttribute, StatementElem, StructElem, StructMemberElem, StuffElem, SwitchClauseElem, SyntheticElem, TerminalElem, TextElem, TrackingResolver, TransformedAST, TranslateTimeExpressionElem, TypeRefElem, TypeTemplateParameter, TypedDeclElem, UnaryExpression, UnaryOperator, UnboundRef, UnknownExpressionElem, VarElem, VirtualLibrary, VirtualLibraryFn, VirtualLibrarySet, WeslAST, WeslBundle, WeslDevice, WeslGPUCompilationInfo, WeslGPUCompilationMessage, WeslJsPlugin, WeslParseContext, WeslParseError, WeslParseState, WeslProject, 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, freshResolver, 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 };
|
|
1280
|
+
export { AbstractElem, AbstractElemBase, AliasElem, Attribute, AttributeElem, BatchModuleResolver, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST, BindingStructElem, BlockStatement, BoundAndTransformed, BuiltinAttribute, BundleResolver, ComponentExpression, ComponentMemberExpression, CompositeResolver, ConditionalAttribute, Conditions, ConstAssertElem, ConstElem, ContainerElem, ContinuingElem, DeclIdent, DeclIdentElem, DeclarationElem, DiagnosticAttribute, DiagnosticDirective, DiagnosticRule, DirectiveElem, DirectiveVariant, ElemKindMap, ElemWithAttributes, ElemWithContentsBase, ElifAttribute, ElseAttribute, EmittableElem, EnableDirective, ExpressionElem, ExtendedGPUValidationError, FnElem, FnParamElem, FunctionCallExpression, GlobalDeclarationElem, GlobalVarElem, GrammarElem, HasAttributes, Ident, IfAttribute, ImportCollection, ImportElem, ImportItem, ImportSegment, ImportStatement, InterpolateAttribute, LetElem, LexicalScope, LinkConfig, LinkParams, LinkRegistryParams, LinkedWesl, LinkerTransform, Literal, LiveDecls, ManglerFn, ModuleElem, ModuleResolver, NameElem, OpenElem, OverrideElem, ParenthesizedExpression, ParseError, type ParseOptions, PartialScope, RecordResolver, RecordResolverOptions, RefIdent, RefIdentElem, RequiresDirective, Scope, ScopeItem, SimpleMemberRef, Span, SrcMap, SrcMapBuilder, SrcMapEntry, SrcModule, SrcPosition, SrcWithPath, StableState, StandardAttribute, StatementElem, StructElem, StructMemberElem, StuffElem, SwitchClauseElem, SyntheticElem, TerminalElem, TextElem, TrackingResolver, TransformedAST, TranslateTimeExpressionElem, TypeRefElem, TypeTemplateParameter, TypedDeclElem, UnaryExpression, UnaryOperator, UnboundRef, UnknownExpressionElem, VarElem, VirtualLibContext, VirtualLibrary, VirtualLibraryFn, VirtualLibrarySet, WeslAST, WeslBundle, WeslDevice, WeslGPUCompilationInfo, WeslGPUCompilationMessage, WeslJsPlugin, WeslParseContext, WeslParseError, WeslParseState, WeslProject, 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, freshResolver, 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 };
|
package/dist/index.js
CHANGED
|
@@ -3633,9 +3633,8 @@ function flatImports(ast, conditions) {
|
|
|
3633
3633
|
//#region src/BindIdents.ts
|
|
3634
3634
|
/** Bind ref idents to declarations and mangle global declaration names. */
|
|
3635
3635
|
function bindIdents(params) {
|
|
3636
|
-
const { rootAst, resolver, virtuals, accumulateUnbound } = params;
|
|
3636
|
+
const { rootAst, resolver, virtuals, accumulateUnbound, discoveryMode } = params;
|
|
3637
3637
|
const { conditions = {}, mangler = minimalMangle } = params;
|
|
3638
|
-
const { discoveryMode } = params;
|
|
3639
3638
|
const packageName = rootAst.srcModule.modulePath.split("::")[0];
|
|
3640
3639
|
const rootDecls = discoveryMode ? findAllRootDecls(rootAst.rootScope) : findValidRootDecls(rootAst.rootScope, conditions);
|
|
3641
3640
|
const { globalNames, knownDecls } = initRootDecls(rootDecls);
|
|
@@ -3646,6 +3645,7 @@ function bindIdents(params) {
|
|
|
3646
3645
|
virtuals,
|
|
3647
3646
|
mangler,
|
|
3648
3647
|
packageName,
|
|
3648
|
+
rootModulePath: rootAst.srcModule.modulePath,
|
|
3649
3649
|
foundScopes: /* @__PURE__ */ new Set(),
|
|
3650
3650
|
globalNames,
|
|
3651
3651
|
globalStatements: /* @__PURE__ */ new Map(),
|
|
@@ -3656,8 +3656,9 @@ function bindIdents(params) {
|
|
|
3656
3656
|
decls: new Map(rootDecls.map((d) => [d.originalName, d])),
|
|
3657
3657
|
parent: null
|
|
3658
3658
|
};
|
|
3659
|
-
const fromRootDecls = rootDecls.flatMap((
|
|
3660
|
-
const
|
|
3659
|
+
const fromRootDecls = rootDecls.flatMap((d) => processDependentScope(d, bindContext));
|
|
3660
|
+
const { rootScope } = rootAst;
|
|
3661
|
+
const fromRefs = bindIdentsRecursive(rootScope, bindContext, liveDecls);
|
|
3661
3662
|
const newStatements = [...bindContext.globalStatements.values()];
|
|
3662
3663
|
return {
|
|
3663
3664
|
decls: [...fromRootDecls, ...fromRefs],
|
|
@@ -3702,11 +3703,7 @@ function findAllRootDecls(rootScope) {
|
|
|
3702
3703
|
function publicDecl(scope, name, conditions) {
|
|
3703
3704
|
return getValidRootDecls(scope, conditions).find((d) => d.originalName === name);
|
|
3704
3705
|
}
|
|
3705
|
-
/**
|
|
3706
|
-
* Recursively bind references to declarations in this scope and child scopes.
|
|
3707
|
-
* Tracks @else state to ensure filtered @else blocks don't pull in unused declarations.
|
|
3708
|
-
* @return new declarations found
|
|
3709
|
-
*/
|
|
3706
|
+
/** Recursively bind refs to decls in this scope and children. @return new declarations found */
|
|
3710
3707
|
function bindIdentsRecursive(scope, bindContext, liveDecls) {
|
|
3711
3708
|
const { dontFollowDecls, foundScopes } = bindContext;
|
|
3712
3709
|
if (foundScopes.has(scope)) return [];
|
|
@@ -3744,11 +3741,7 @@ function processDependentScope(decl, ctx) {
|
|
|
3744
3741
|
if (!rootDecls) return [];
|
|
3745
3742
|
return bindIdentsRecursive(dependentScope, ctx, makeLiveDecls(rootDecls));
|
|
3746
3743
|
}
|
|
3747
|
-
/**
|
|
3748
|
-
* Trace references to their declarations.
|
|
3749
|
-
* Mutates to mangle declarations and mark std references.
|
|
3750
|
-
* @return found declaration, or undefined if already processed
|
|
3751
|
-
*/
|
|
3744
|
+
/** Resolve a ref to its declaration, mangling globals and marking std refs. */
|
|
3752
3745
|
function handleRef(ident, liveDecls, bindContext) {
|
|
3753
3746
|
if (ident.refersTo || ident.std) return;
|
|
3754
3747
|
if (ident.conditionRef) return;
|
|
@@ -3828,7 +3821,8 @@ function findExport(pathParts, srcModule, ctx) {
|
|
|
3828
3821
|
const modulePath = resolveModulePath(pathParts, srcModule.modulePath.split("::")).slice(0, -1).join("::");
|
|
3829
3822
|
const moduleAst = ctx.resolver.resolveModule(modulePath) ?? virtualModule(pathParts[0], ctx);
|
|
3830
3823
|
if (!moduleAst) return void 0;
|
|
3831
|
-
const
|
|
3824
|
+
const name = last(pathParts);
|
|
3825
|
+
const decl = publicDecl(moduleAst.rootScope, name, ctx.conditions);
|
|
3832
3826
|
if (decl) return {
|
|
3833
3827
|
decl,
|
|
3834
3828
|
moduleAst
|
|
@@ -3839,9 +3833,14 @@ function virtualModule(moduleName, ctx) {
|
|
|
3839
3833
|
const found = ctx.virtuals?.[moduleName];
|
|
3840
3834
|
if (!found) return void 0;
|
|
3841
3835
|
if (found.ast) return found.ast;
|
|
3842
|
-
const
|
|
3836
|
+
const { conditions, rootModulePath, packageName } = ctx;
|
|
3837
|
+
const src = found.fn({
|
|
3838
|
+
conditions,
|
|
3839
|
+
rootModulePath,
|
|
3840
|
+
packageName
|
|
3841
|
+
});
|
|
3843
3842
|
found.ast = parseSrcModule({
|
|
3844
|
-
modulePath:
|
|
3843
|
+
modulePath: packageName + "::" + moduleName,
|
|
3845
3844
|
debugFilePath: moduleName,
|
|
3846
3845
|
src
|
|
3847
3846
|
});
|
|
@@ -3861,8 +3860,8 @@ function rootLiveDecls(decl, conditions) {
|
|
|
3861
3860
|
assertThatDebug(scope.kind === "scope");
|
|
3862
3861
|
const root = scope;
|
|
3863
3862
|
if (!root._scopeDecls) {
|
|
3864
|
-
const
|
|
3865
|
-
root._scopeDecls = { decls: new Map(
|
|
3863
|
+
const decls = findValidRootDecls(scope, conditions);
|
|
3864
|
+
root._scopeDecls = { decls: new Map(decls.map((d) => [d.originalName, d])) };
|
|
3866
3865
|
}
|
|
3867
3866
|
return root._scopeDecls;
|
|
3868
3867
|
}
|
|
@@ -4083,6 +4082,7 @@ function findUnboundRefs(resolver) {
|
|
|
4083
4082
|
globalStatements: /* @__PURE__ */ new Map(),
|
|
4084
4083
|
mangler: minimalMangle,
|
|
4085
4084
|
packageName: "package",
|
|
4085
|
+
rootModulePath: "package::main",
|
|
4086
4086
|
unbound: [],
|
|
4087
4087
|
dontFollowDecls: true,
|
|
4088
4088
|
discoveryMode: true
|
|
@@ -4515,8 +4515,9 @@ function flattenLibraryTree(libs) {
|
|
|
4515
4515
|
* that share some sources.)
|
|
4516
4516
|
*/
|
|
4517
4517
|
function linkRegistry(params) {
|
|
4518
|
-
const { transformedAst, newDecls, newStatements } = bindAndTransform(params);
|
|
4519
|
-
|
|
4518
|
+
const { transformedAst: ast, newDecls, newStatements } = bindAndTransform(params);
|
|
4519
|
+
const builders = emitWgsl(ast.moduleElem, ast.srcModule, newDecls, newStatements, params.conditions);
|
|
4520
|
+
return SrcMapBuilder.build(builders);
|
|
4520
4521
|
}
|
|
4521
4522
|
/** Bind identifiers and apply transform plugins */
|
|
4522
4523
|
function bindAndTransform(params) {
|
|
@@ -4574,6 +4575,7 @@ function applyTransformPlugins(rootModule, globalNames, config) {
|
|
|
4574
4575
|
};
|
|
4575
4576
|
return filterMap(config?.plugins ?? [], (plugin) => plugin.transform).reduce((ast, transform) => transform(ast), startAst);
|
|
4576
4577
|
}
|
|
4578
|
+
/** Assemble WGSL output from prologue statements, root module, and imported declarations. */
|
|
4577
4579
|
function emitWgsl(rootModuleElem, srcModule, newDecls, newStatements, conditions = {}) {
|
|
4578
4580
|
const prologueBuilders = newStatements.map((s) => emitStatement(s, conditions));
|
|
4579
4581
|
const rootBuilder = new SrcMapBuilder({
|
package/package.json
CHANGED
package/src/BindIdents.ts
CHANGED
|
@@ -28,23 +28,12 @@ import {
|
|
|
28
28
|
import { last } from "./Util.ts";
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* BindIdents pass:
|
|
31
|
+
* BindIdents pass: depth-first walk of the scope tree (not syntax tree),
|
|
32
|
+
* linking ref idents to declarations and mangling global names.
|
|
32
33
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* - Create mangled names for globals to avoid conflicts
|
|
37
|
-
*
|
|
38
|
-
* Algorithm:
|
|
39
|
-
* - Recursive depth-first walk of scope tree (not syntax tree)
|
|
40
|
-
* - For each ref: search current scope, then up to parent scopes
|
|
41
|
-
* - If no local match: check import statements for external matches
|
|
42
|
-
* - For found global decls: mangle name to be unique, collect for emission
|
|
43
|
-
*
|
|
44
|
-
* LiveDecls: tracks visible declarations at the current position, with parent links.
|
|
45
|
-
*
|
|
46
|
-
* @if/@else: respects conditional compilation by tracking @else validity state,
|
|
47
|
-
* mirroring the emission phase's filterValidElements but on scopes.
|
|
34
|
+
* For each ref: search current scope upward, then check imports for external matches.
|
|
35
|
+
* LiveDecls tracks visible declarations with parent links.
|
|
36
|
+
* @if/@else: mirrors filterValidElements but on scopes.
|
|
48
37
|
*/
|
|
49
38
|
|
|
50
39
|
/** Results returned from binding pass. */
|
|
@@ -107,9 +96,9 @@ export interface BindIdentsParams
|
|
|
107
96
|
|
|
108
97
|
/** Bind ref idents to declarations and mangle global declaration names. */
|
|
109
98
|
export function bindIdents(params: BindIdentsParams): BindResults {
|
|
110
|
-
const { rootAst, resolver, virtuals, accumulateUnbound } =
|
|
99
|
+
const { rootAst, resolver, virtuals, accumulateUnbound, discoveryMode } =
|
|
100
|
+
params;
|
|
111
101
|
const { conditions = {}, mangler = minimalMangle } = params;
|
|
112
|
-
const { discoveryMode } = params;
|
|
113
102
|
const packageName = rootAst.srcModule.modulePath.split("::")[0];
|
|
114
103
|
|
|
115
104
|
const rootDecls = discoveryMode
|
|
@@ -117,6 +106,7 @@ export function bindIdents(params: BindIdentsParams): BindResults {
|
|
|
117
106
|
: findValidRootDecls(rootAst.rootScope, conditions);
|
|
118
107
|
const { globalNames, knownDecls } = initRootDecls(rootDecls);
|
|
119
108
|
|
|
109
|
+
const rootModulePath = rootAst.srcModule.modulePath;
|
|
120
110
|
const bindContext = {
|
|
121
111
|
resolver,
|
|
122
112
|
conditions,
|
|
@@ -124,6 +114,7 @@ export function bindIdents(params: BindIdentsParams): BindResults {
|
|
|
124
114
|
virtuals,
|
|
125
115
|
mangler,
|
|
126
116
|
packageName,
|
|
117
|
+
rootModulePath,
|
|
127
118
|
foundScopes: new Set<Scope>(),
|
|
128
119
|
globalNames,
|
|
129
120
|
globalStatements: new Map<AbstractElem, EmittableElem>(),
|
|
@@ -134,15 +125,11 @@ export function bindIdents(params: BindIdentsParams): BindResults {
|
|
|
134
125
|
const decls = new Map(rootDecls.map(d => [d.originalName, d] as const));
|
|
135
126
|
const liveDecls: LiveDecls = { decls, parent: null };
|
|
136
127
|
|
|
137
|
-
const fromRootDecls = rootDecls.flatMap(
|
|
138
|
-
processDependentScope(
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
const fromRefs = bindIdentsRecursive(
|
|
142
|
-
rootAst.rootScope,
|
|
143
|
-
bindContext,
|
|
144
|
-
liveDecls,
|
|
128
|
+
const fromRootDecls = rootDecls.flatMap(d =>
|
|
129
|
+
processDependentScope(d, bindContext),
|
|
145
130
|
);
|
|
131
|
+
const { rootScope } = rootAst;
|
|
132
|
+
const fromRefs = bindIdentsRecursive(rootScope, bindContext, liveDecls);
|
|
146
133
|
const newStatements = [...bindContext.globalStatements.values()];
|
|
147
134
|
return {
|
|
148
135
|
decls: [...fromRootDecls, ...fromRefs],
|
|
@@ -233,6 +220,9 @@ interface BindContext {
|
|
|
233
220
|
/** Host package name for resolving package:: in virtual modules. */
|
|
234
221
|
packageName: string;
|
|
235
222
|
|
|
223
|
+
/** Root module path (e.g., "package::main"). */
|
|
224
|
+
rootModulePath: string;
|
|
225
|
+
|
|
236
226
|
/** Unbound identifiers if accumulateUnbound is true. */
|
|
237
227
|
unbound?: UnboundRef[];
|
|
238
228
|
|
|
@@ -243,11 +233,7 @@ interface BindContext {
|
|
|
243
233
|
discoveryMode?: boolean;
|
|
244
234
|
}
|
|
245
235
|
|
|
246
|
-
/**
|
|
247
|
-
* Recursively bind references to declarations in this scope and child scopes.
|
|
248
|
-
* Tracks @else state to ensure filtered @else blocks don't pull in unused declarations.
|
|
249
|
-
* @return new declarations found
|
|
250
|
-
*/
|
|
236
|
+
/** Recursively bind refs to decls in this scope and children. @return new declarations found */
|
|
251
237
|
export function bindIdentsRecursive(
|
|
252
238
|
scope: Scope,
|
|
253
239
|
bindContext: BindContext,
|
|
@@ -257,8 +243,11 @@ export function bindIdentsRecursive(
|
|
|
257
243
|
if (foundScopes.has(scope)) return [];
|
|
258
244
|
foundScopes.add(scope);
|
|
259
245
|
|
|
260
|
-
const
|
|
261
|
-
|
|
246
|
+
const { newGlobals, newFromChildren } = processScope(
|
|
247
|
+
scope,
|
|
248
|
+
bindContext,
|
|
249
|
+
liveDecls,
|
|
250
|
+
);
|
|
262
251
|
const newFromRefs = dontFollowDecls
|
|
263
252
|
? []
|
|
264
253
|
: handleDecls(newGlobals, bindContext);
|
|
@@ -301,11 +290,7 @@ function processDependentScope(decl: DeclIdent, ctx: BindContext): DeclIdent[] {
|
|
|
301
290
|
return bindIdentsRecursive(dependentScope, ctx, makeLiveDecls(rootDecls));
|
|
302
291
|
}
|
|
303
292
|
|
|
304
|
-
/**
|
|
305
|
-
* Trace references to their declarations.
|
|
306
|
-
* Mutates to mangle declarations and mark std references.
|
|
307
|
-
* @return found declaration, or undefined if already processed
|
|
308
|
-
*/
|
|
293
|
+
/** Resolve a ref to its declaration, mangling globals and marking std refs. */
|
|
309
294
|
function handleRef(
|
|
310
295
|
ident: RefIdent,
|
|
311
296
|
liveDecls: LiveDecls,
|
|
@@ -443,11 +428,8 @@ function findExport(
|
|
|
443
428
|
ctx.resolver.resolveModule(modulePath) ?? virtualModule(pathParts[0], ctx);
|
|
444
429
|
if (!moduleAst) return undefined;
|
|
445
430
|
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
last(pathParts)!,
|
|
449
|
-
ctx.conditions,
|
|
450
|
-
);
|
|
431
|
+
const name = last(pathParts)!;
|
|
432
|
+
const decl = publicDecl(moduleAst.rootScope, name, ctx.conditions);
|
|
451
433
|
if (decl) return { decl, moduleAst };
|
|
452
434
|
}
|
|
453
435
|
|
|
@@ -460,10 +442,10 @@ function virtualModule(
|
|
|
460
442
|
if (!found) return undefined;
|
|
461
443
|
if (found.ast) return found.ast;
|
|
462
444
|
|
|
463
|
-
const
|
|
464
|
-
const
|
|
465
|
-
const
|
|
466
|
-
found.ast = parseSrcModule({ modulePath, debugFilePath, src });
|
|
445
|
+
const { conditions, rootModulePath, packageName } = ctx;
|
|
446
|
+
const src = found.fn({ conditions, rootModulePath, packageName });
|
|
447
|
+
const modulePath = packageName + "::" + moduleName;
|
|
448
|
+
found.ast = parseSrcModule({ modulePath, debugFilePath: moduleName, src });
|
|
467
449
|
return found.ast;
|
|
468
450
|
}
|
|
469
451
|
|
|
@@ -490,10 +472,8 @@ function rootLiveDecls(
|
|
|
490
472
|
|
|
491
473
|
const root = scope as LexicalScope;
|
|
492
474
|
if (!root._scopeDecls) {
|
|
493
|
-
const
|
|
494
|
-
root._scopeDecls = {
|
|
495
|
-
decls: new Map(rootDecls.map(d => [d.originalName, d])),
|
|
496
|
-
};
|
|
475
|
+
const decls = findValidRootDecls(scope, conditions);
|
|
476
|
+
root._scopeDecls = { decls: new Map(decls.map(d => [d.originalName, d])) };
|
|
497
477
|
}
|
|
498
478
|
return root._scopeDecls;
|
|
499
479
|
}
|
package/src/Linker.ts
CHANGED
|
@@ -102,8 +102,15 @@ export type WeslProject = Pick<
|
|
|
102
102
|
| "packageName"
|
|
103
103
|
>;
|
|
104
104
|
|
|
105
|
-
/**
|
|
106
|
-
export
|
|
105
|
+
/** Context passed to virtual library generators. */
|
|
106
|
+
export interface VirtualLibContext {
|
|
107
|
+
conditions: Conditions;
|
|
108
|
+
rootModulePath: string;
|
|
109
|
+
packageName: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Generate a virtual WESL module. */
|
|
113
|
+
export type VirtualLibraryFn = (ctx: VirtualLibContext) => string;
|
|
107
114
|
|
|
108
115
|
/**
|
|
109
116
|
* Link a set of WESL source modules (typically the text from .wesl files) into a single WGSL string.
|
|
@@ -193,18 +200,19 @@ export interface LinkRegistryParams
|
|
|
193
200
|
* that share some sources.)
|
|
194
201
|
*/
|
|
195
202
|
export function linkRegistry(params: LinkRegistryParams): SrcMap {
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
203
|
+
const {
|
|
204
|
+
transformedAst: ast,
|
|
205
|
+
newDecls,
|
|
206
|
+
newStatements,
|
|
207
|
+
} = bindAndTransform(params);
|
|
208
|
+
const builders = emitWgsl(
|
|
209
|
+
ast.moduleElem,
|
|
210
|
+
ast.srcModule,
|
|
211
|
+
newDecls,
|
|
212
|
+
newStatements,
|
|
213
|
+
params.conditions,
|
|
207
214
|
);
|
|
215
|
+
return SrcMapBuilder.build(builders);
|
|
208
216
|
}
|
|
209
217
|
|
|
210
218
|
export interface BoundAndTransformed {
|
|
@@ -225,15 +233,14 @@ export function bindAndTransform(
|
|
|
225
233
|
|
|
226
234
|
const virtuals = setupVirtualLibs(params.virtualLibs, constants);
|
|
227
235
|
|
|
228
|
-
const
|
|
236
|
+
const bound = bindIdents({
|
|
229
237
|
rootAst,
|
|
230
238
|
resolver,
|
|
231
239
|
conditions,
|
|
232
240
|
virtuals,
|
|
233
241
|
mangler,
|
|
234
|
-
};
|
|
235
|
-
const
|
|
236
|
-
const { globalNames, decls: newDecls, newStatements } = bindResults;
|
|
242
|
+
});
|
|
243
|
+
const { globalNames, decls: newDecls, newStatements } = bound;
|
|
237
244
|
|
|
238
245
|
const transformedAst = applyTransformPlugins(rootAst, globalNames, config);
|
|
239
246
|
return { transformedAst, newDecls, newStatements };
|
|
@@ -275,7 +282,7 @@ function setupVirtualLibs(
|
|
|
275
282
|
): VirtualLibrarySet | undefined {
|
|
276
283
|
let libs = virtualLibs;
|
|
277
284
|
if (constants) {
|
|
278
|
-
const constantsGen = () =>
|
|
285
|
+
const constantsGen: VirtualLibraryFn = () =>
|
|
279
286
|
Object.entries(constants)
|
|
280
287
|
.map(([name, value]) => `const ${name} = ${value};`)
|
|
281
288
|
.join("\n");
|
|
@@ -295,14 +302,10 @@ function applyTransformPlugins(
|
|
|
295
302
|
const startAst = { moduleElem, srcModule, globalNames, notableElems: {} };
|
|
296
303
|
const plugins = config?.plugins ?? [];
|
|
297
304
|
const transforms = filterMap(plugins, plugin => plugin.transform);
|
|
298
|
-
|
|
299
|
-
(ast, transform) => transform(ast),
|
|
300
|
-
startAst,
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
return transformedAst;
|
|
305
|
+
return transforms.reduce((ast, transform) => transform(ast), startAst);
|
|
304
306
|
}
|
|
305
307
|
|
|
308
|
+
/** Assemble WGSL output from prologue statements, root module, and imported declarations. */
|
|
306
309
|
function emitWgsl(
|
|
307
310
|
rootModuleElem: ModuleElem,
|
|
308
311
|
srcModule: SrcModule,
|
|
@@ -353,7 +356,6 @@ function emitDecl(decl: DeclIdent, conditions: Conditions): SrcMapBuilder {
|
|
|
353
356
|
return builder;
|
|
354
357
|
}
|
|
355
358
|
|
|
356
|
-
/* ---- Commentary on present and future features ---- */
|
|
357
359
|
/*
|
|
358
360
|
|
|
359
361
|
LATER
|
|
@@ -42,6 +42,7 @@ export function findUnboundRefs(resolver: BatchModuleResolver): UnboundRef[] {
|
|
|
42
42
|
globalStatements: new Map<AbstractElem, EmittableElem>(),
|
|
43
43
|
mangler: minimalMangle,
|
|
44
44
|
packageName: "package",
|
|
45
|
+
rootModulePath: "package::main",
|
|
45
46
|
unbound: [] as UnboundRef[],
|
|
46
47
|
dontFollowDecls: true,
|
|
47
48
|
discoveryMode: true,
|