wesl 0.6.15 → 0.6.17
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/README.md +1 -1
- package/dist/index.d.ts +121 -33
- package/dist/index.js +296 -203
- package/package.json +3 -3
- package/src/BindIdents.ts +97 -118
- package/src/Linker.ts +149 -77
- package/src/ModuleResolver.ts +233 -0
- package/src/index.ts +2 -1
- package/src/test/BindWESL.test.ts +9 -15
- package/src/test/ErrorLogging.test.ts +16 -0
- package/src/test/TestUtil.ts +19 -28
- package/src/test/TransformBindingStructs.test.ts +8 -5
- package/src/ParsedRegistry.ts +0 -115
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ WESL adds features:
|
|
|
20
20
|
- **shader libraries** on npm and cargo, for community sharing of shader code modules
|
|
21
21
|
|
|
22
22
|
This [wesl] library contains a **TypeScript** WESL linker.
|
|
23
|
-
[wesl] can be used at runtime or at build time to assemble WESL and WGSL modules for
|
|
23
|
+
[wesl] can be used at runtime or at build time to assemble WESL and WGSL modules for WebGPU.
|
|
24
24
|
|
|
25
25
|
<img style="margin:10px 0px -10px 40px" src="https://docs.google.com/drawings/d/e/2PACX-1vRKxcnMB-U-UVcDRO6N6UMJESTodUBRnV6cVrrS_XwJetucnOfYCU9ztk9veXoqLJ7DinBdDnR9EiK-/pub?w=400&h=300">
|
|
26
26
|
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,10 @@ interface LiveDecls {
|
|
|
8
8
|
/** live decls in the parent scope. null for the modue root scope */
|
|
9
9
|
parent?: LiveDecls | null;
|
|
10
10
|
}
|
|
11
|
+
/** create a LiveDecls */
|
|
12
|
+
declare function makeLiveDecls(parent?: LiveDecls | null): LiveDecls;
|
|
13
|
+
/** debug routine for logging LiveDecls */
|
|
14
|
+
declare function liveDeclsToString(liveDecls: LiveDecls): string;
|
|
11
15
|
//#endregion
|
|
12
16
|
//#region src/FlattenTreeImport.d.ts
|
|
13
17
|
interface FlatImport {
|
|
@@ -608,30 +612,6 @@ declare function minimalMangle(_d: DeclIdent, _s: SrcModule, proposedName: strin
|
|
|
608
612
|
*/
|
|
609
613
|
declare function minimallyMangledName(proposedName: string, globalNames: Set<string>): string;
|
|
610
614
|
//#endregion
|
|
611
|
-
//#region src/ParsedRegistry.d.ts
|
|
612
|
-
interface ParsedRegistry {
|
|
613
|
-
modules: Record<string, WeslAST>;
|
|
614
|
-
}
|
|
615
|
-
declare function parsedRegistry(): ParsedRegistry;
|
|
616
|
-
/** for debug */
|
|
617
|
-
declare function registryToString(registry: ParsedRegistry): string;
|
|
618
|
-
/** Look up a module with a flexible selector.
|
|
619
|
-
* :: separated module path, package::util
|
|
620
|
-
* / separated file path ./util.wesl (or ./util)
|
|
621
|
-
* - note: a file path should not include a weslRoot prefix, e.g. not ./shaders/util.wesl
|
|
622
|
-
* simpleName util
|
|
623
|
-
*/
|
|
624
|
-
declare function selectModule(parsed: ParsedRegistry, selectPath: string, packageName?: string): WeslAST | undefined;
|
|
625
|
-
/**
|
|
626
|
-
* @param srcFiles map of source strings by file path
|
|
627
|
-
* key is '/' separated relative path (relative to srcRoot, not absolute file path )
|
|
628
|
-
* value is wesl source string
|
|
629
|
-
* @param registry add parsed modules to this registry
|
|
630
|
-
* @param packageName name of package
|
|
631
|
-
*/
|
|
632
|
-
declare function parseIntoRegistry(srcFiles: Record<string, string>, registry: ParsedRegistry, packageName?: string, debugWeslRoot?: string): void;
|
|
633
|
-
declare function parseLibsIntoRegistry(libs: WeslBundle[], registry: ParsedRegistry): void;
|
|
634
|
-
//#endregion
|
|
635
615
|
//#region src/WeslBundle.d.ts
|
|
636
616
|
interface WeslBundle {
|
|
637
617
|
/** name of the package, e.g. random_wgsl */
|
|
@@ -647,6 +627,68 @@ interface WeslBundle {
|
|
|
647
627
|
dependencies?: WeslBundle[];
|
|
648
628
|
}
|
|
649
629
|
//#endregion
|
|
630
|
+
//#region src/ModuleResolver.d.ts
|
|
631
|
+
/**
|
|
632
|
+
* Resolves module paths to parsed ASTs.
|
|
633
|
+
*
|
|
634
|
+
* Implementations may cache ASTs or load them lazily.
|
|
635
|
+
*/
|
|
636
|
+
interface ModuleResolver {
|
|
637
|
+
/**
|
|
638
|
+
* Resolve a module path to its parsed AST.
|
|
639
|
+
*
|
|
640
|
+
* @param modulePath - Module path in :: format (e.g., "package::foo::bar")
|
|
641
|
+
* @returns Parsed AST or undefined if module not found
|
|
642
|
+
*/
|
|
643
|
+
resolveModule(modulePath: string): WeslAST | undefined;
|
|
644
|
+
}
|
|
645
|
+
/** Module resolver that supports batch enumeration of all modules. */
|
|
646
|
+
interface BatchModuleResolver extends ModuleResolver {
|
|
647
|
+
/**
|
|
648
|
+
* Return all modules, parsing them on-demand if needed.
|
|
649
|
+
* Implementations should ensure all sources are parsed before returning.
|
|
650
|
+
*/
|
|
651
|
+
allModules(): Iterable<[string, WeslAST]>;
|
|
652
|
+
}
|
|
653
|
+
interface RecordResolverOptions {
|
|
654
|
+
/** Package name for module path resolution (default: "package") */
|
|
655
|
+
packageName?: string;
|
|
656
|
+
/** Debug path prefix for error messages */
|
|
657
|
+
debugWeslRoot?: string;
|
|
658
|
+
}
|
|
659
|
+
/** Module resolver for in-memory source records. Lazy by default. */
|
|
660
|
+
declare class RecordResolver implements BatchModuleResolver {
|
|
661
|
+
readonly astCache: Map<string, WeslAST>;
|
|
662
|
+
readonly sources: Record<string, string>;
|
|
663
|
+
readonly packageName: string;
|
|
664
|
+
readonly debugWeslRoot: string;
|
|
665
|
+
constructor(sources: Record<string, string>, options?: RecordResolverOptions);
|
|
666
|
+
resolveModule(modulePath: string): WeslAST | undefined;
|
|
667
|
+
private findSource;
|
|
668
|
+
private moduleToFilePath;
|
|
669
|
+
private modulePathToDebugPath;
|
|
670
|
+
/** Return all modules, parsing them on-demand if needed. */
|
|
671
|
+
allModules(): Iterable<[string, WeslAST]>;
|
|
672
|
+
}
|
|
673
|
+
/** Composite resolver that tries each resolver in order until one succeeds. */
|
|
674
|
+
declare class CompositeResolver implements ModuleResolver {
|
|
675
|
+
readonly resolvers: ModuleResolver[];
|
|
676
|
+
constructor(resolvers: ModuleResolver[]);
|
|
677
|
+
resolveModule(modulePath: string): WeslAST | undefined;
|
|
678
|
+
}
|
|
679
|
+
/** Lazy resolver for WeslBundle library modules. */
|
|
680
|
+
declare class BundleResolver implements ModuleResolver {
|
|
681
|
+
private readonly astCache;
|
|
682
|
+
private readonly sources;
|
|
683
|
+
private readonly packageName;
|
|
684
|
+
private readonly debugWeslRoot;
|
|
685
|
+
constructor(bundle: WeslBundle, debugWeslRoot?: string);
|
|
686
|
+
resolveModule(modulePath: string): WeslAST | undefined;
|
|
687
|
+
private findSource;
|
|
688
|
+
private moduleToFilePath;
|
|
689
|
+
private modulePathToDebugPath;
|
|
690
|
+
}
|
|
691
|
+
//#endregion
|
|
650
692
|
//#region src/Linker.d.ts
|
|
651
693
|
type LinkerTransform = (boundAST: TransformedAST) => TransformedAST;
|
|
652
694
|
interface WeslJsPlugin {
|
|
@@ -660,7 +702,11 @@ interface LinkConfig {
|
|
|
660
702
|
plugins?: WeslJsPlugin[];
|
|
661
703
|
}
|
|
662
704
|
interface LinkParams {
|
|
663
|
-
/**
|
|
705
|
+
/** Module resolver for lazy loading (NEW API - preferred)
|
|
706
|
+
* Replaces weslSrc for lazy module loading.
|
|
707
|
+
* If provided, weslSrc will be ignored. */
|
|
708
|
+
resolver?: ModuleResolver;
|
|
709
|
+
/** record of file paths and wesl text for modules (LEGACY API - still supported).
|
|
664
710
|
* key is module path or file path
|
|
665
711
|
* `package::foo::bar`, or './foo/bar.wesl', or './foo/bar'
|
|
666
712
|
* value is wesl src
|
|
@@ -671,7 +717,7 @@ interface LinkParams {
|
|
|
671
717
|
* - Valid WGSL identifiers: No backslashes, no `..`, or other non-identifier symbols.
|
|
672
718
|
* - Relative paths: They have to be relative to the wesl root.
|
|
673
719
|
*/
|
|
674
|
-
weslSrc
|
|
720
|
+
weslSrc?: Record<string, string>;
|
|
675
721
|
/** name of root wesl module
|
|
676
722
|
* for an app, the root module normally contains the '@compute', '@vertex' or '@fragment' entry points
|
|
677
723
|
* for a library, the root module defines the public api fo the library
|
|
@@ -686,6 +732,10 @@ interface LinkParams {
|
|
|
686
732
|
libs?: WeslBundle[];
|
|
687
733
|
/** generate wesl from code at runtime */
|
|
688
734
|
virtualLibs?: Record<string, VirtualLibraryFn>;
|
|
735
|
+
/** package name for the local sources (in addition to default "package::").
|
|
736
|
+
* Enables imports like `import mypkg::foo` alongside `import package::foo`.
|
|
737
|
+
* Package names with hyphens should be normalized to underscores. */
|
|
738
|
+
packageName?: string;
|
|
689
739
|
/** plugins and other configuration to use while linking */
|
|
690
740
|
config?: LinkConfig;
|
|
691
741
|
/** Host (ts/js) provided wgsl constants.
|
|
@@ -708,9 +758,9 @@ type VirtualLibraryFn = (conditions: Conditions) => string;
|
|
|
708
758
|
*/
|
|
709
759
|
declare function link(params: LinkParams): Promise<LinkedWesl>;
|
|
710
760
|
/** linker api for benchmarking */
|
|
711
|
-
declare function _linkSync(params: LinkParams):
|
|
761
|
+
declare function _linkSync(params: LinkParams): SrcMap;
|
|
712
762
|
interface LinkRegistryParams extends Pick<LinkParams, "rootModuleName" | "conditions" | "virtualLibs" | "config" | "constants" | "mangler"> {
|
|
713
|
-
|
|
763
|
+
resolver: ModuleResolver;
|
|
714
764
|
}
|
|
715
765
|
/** Link wesl from a registry of already parsed modules.
|
|
716
766
|
*
|
|
@@ -725,8 +775,11 @@ interface BoundAndTransformed {
|
|
|
725
775
|
newDecls: DeclIdent[];
|
|
726
776
|
newStatements: EmittableElem[];
|
|
727
777
|
}
|
|
728
|
-
/**
|
|
778
|
+
/** Bind identifiers and apply transform plugins */
|
|
729
779
|
declare function bindAndTransform(params: LinkRegistryParams): BoundAndTransformed;
|
|
780
|
+
/** Convert root module name to module path format.
|
|
781
|
+
* Accepts: module path (package::foo), file path (./foo.wesl), or name (foo) */
|
|
782
|
+
declare function normalizeModuleName(name: string): string;
|
|
730
783
|
//#endregion
|
|
731
784
|
//#region src/BindIdents.d.ts
|
|
732
785
|
/**
|
|
@@ -783,7 +836,7 @@ interface VirtualLibrary {
|
|
|
783
836
|
}
|
|
784
837
|
/** key is virtual module name */
|
|
785
838
|
type VirtualLibrarySet = Record<string, VirtualLibrary>;
|
|
786
|
-
interface BindIdentsParams extends Pick<LinkRegistryParams, "
|
|
839
|
+
interface BindIdentsParams extends Pick<LinkRegistryParams, "resolver" | "conditions" | "mangler"> {
|
|
787
840
|
rootAst: WeslAST;
|
|
788
841
|
virtuals?: VirtualLibrarySet;
|
|
789
842
|
/** if false, throw on unbound identifiers. If true, accumulate unbound identifiers into
|
|
@@ -799,8 +852,6 @@ interface BindIdentsParams extends Pick<LinkRegistryParams, "registry" | "condit
|
|
|
799
852
|
* @return any new declaration elements found (they will need to be emitted)
|
|
800
853
|
*/
|
|
801
854
|
declare function bindIdents(params: BindIdentsParams): BindResults;
|
|
802
|
-
/** bind local references in library sources to reveal references to external packages */
|
|
803
|
-
declare function findUnboundIdents(registry: ParsedRegistry): string[][];
|
|
804
855
|
/**
|
|
805
856
|
* Find all conditionally valid declarations at the root level.
|
|
806
857
|
* Declarations are either directly in the root scope or in conditionally valid partial scopes.
|
|
@@ -821,6 +872,43 @@ declare function findValidRootDecls(rootScope: Scope, conditions: Conditions): D
|
|
|
821
872
|
declare function publicDecl(scope: Scope, name: string, conditions: Conditions): DeclIdent | undefined;
|
|
822
873
|
/** @return true if this decl is at the root scope level of a module */
|
|
823
874
|
declare function isGlobal(declIdent: DeclIdent): boolean;
|
|
875
|
+
/** state used during the recursive scope tree walk to bind references to declarations */
|
|
876
|
+
interface BindContext {
|
|
877
|
+
resolver: ModuleResolver;
|
|
878
|
+
conditions: Record<string, any>;
|
|
879
|
+
/** decl idents discovered so far (to avoid re-traversing) */
|
|
880
|
+
knownDecls: Set<DeclIdent>;
|
|
881
|
+
/** save work by not processing scopes multiple times */
|
|
882
|
+
foundScopes: Set<Scope>;
|
|
883
|
+
/** root level names used so far (enables manglers/plugins to pick unique names) */
|
|
884
|
+
globalNames: Set<string>;
|
|
885
|
+
/** additional global statements to emit (e.g. module level const_assert, indexed by elem for uniqueness) */
|
|
886
|
+
globalStatements: Map<AbstractElem, EmittableElem>;
|
|
887
|
+
/** construct unique identifer names for global declarations */
|
|
888
|
+
mangler: ManglerFn;
|
|
889
|
+
virtuals?: VirtualLibrarySet;
|
|
890
|
+
/** list of unbound identifiers if accumulateUnbound is true */
|
|
891
|
+
unbound?: string[][];
|
|
892
|
+
/** don't follow references from declarations (used for library dependency detection) */
|
|
893
|
+
dontFollowDecls?: boolean;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Recursively bind references to declarations in this scope and
|
|
897
|
+
* any child scopes referenced by these declarations.
|
|
898
|
+
* Uses a hash set of found declarations to avoid duplication.
|
|
899
|
+
*
|
|
900
|
+
* IMPORTANT: This function tracks @else state while traversing sibling scopes.
|
|
901
|
+
* When an @if scope is processed, its validity determines whether the following
|
|
902
|
+
* @else scope should be considered valid. This ensures that references from
|
|
903
|
+
* filtered @else blocks don't pull in unused declarations.
|
|
904
|
+
*
|
|
905
|
+
* @return any new declarations found
|
|
906
|
+
* @param liveDecls current set of live declaration in this scope
|
|
907
|
+
* (empty when traversing to a new scope, possibly non-empty for a partial scope)
|
|
908
|
+
* @param isRoot liveDecls refers to a prepopulated root scope
|
|
909
|
+
* (root scope declarations may appear in any order)
|
|
910
|
+
*/
|
|
911
|
+
declare function bindIdentsRecursive(scope: Scope, bindContext: BindContext, liveDecls: LiveDecls, isRoot?: boolean): DeclIdent[];
|
|
824
912
|
//#endregion
|
|
825
913
|
//#region src/debug/ASTtoString.d.ts
|
|
826
914
|
declare function astToString(elem: AbstractElem, indent?: number): string;
|
|
@@ -974,4 +1062,4 @@ declare function offsetToLineNumber(offset: number, text: string): [lineNum: num
|
|
|
974
1062
|
*/
|
|
975
1063
|
declare function errorHighlight(source: string, span: Span): [string, string];
|
|
976
1064
|
//#endregion
|
|
977
|
-
export { AbstractElem, AbstractElemBase, AliasElem, Attribute, AttributeElem, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST, BindingStructElem, BoundAndTransformed, BuiltinAttribute, ComponentExpression, ComponentMemberExpression, Conditions, ConstAssertElem, ConstElem, ContainerElem, DeclIdent, DeclIdentElem, DeclarationElem, DiagnosticAttribute, DiagnosticDirective, DirectiveElem, DirectiveVariant, 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, ManglerFn, ModuleElem, NameElem, OverrideElem, ParenthesizedExpression,
|
|
1065
|
+
export { AbstractElem, AbstractElemBase, AliasElem, Attribute, AttributeElem, BatchModuleResolver, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST, BindingStructElem, BoundAndTransformed, BuiltinAttribute, BundleResolver, ComponentExpression, ComponentMemberExpression, CompositeResolver, Conditions, ConstAssertElem, ConstElem, ContainerElem, DeclIdent, DeclIdentElem, DeclarationElem, DiagnosticAttribute, DiagnosticDirective, DirectiveElem, DirectiveVariant, 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, OverrideElem, ParenthesizedExpression, PartialScope, RecordResolver, RecordResolverOptions, RefIdent, RefIdentElem, RequiresDirective, Scope, SimpleMemberRef, SrcModule, StableState, StandardAttribute, StatementElem, StructElem, StructMemberElem, StuffElem, SwitchClauseElem, SyntheticElem, TerminalElem, TextElem, TransformedAST, TranslateTimeExpressionElem, TranslateTimeFeature, TypeRefElem, TypeTemplateParameter, TypedDeclElem, UnaryExpression, UnaryOperator, UnknownExpressionElem, VarElem, VirtualLibrary, VirtualLibraryFn, VirtualLibrarySet, WeslAST, WeslBundle, WeslDevice, WeslGPUCompilationInfo, WeslGPUCompilationMessage, WeslJsPlugin, WeslParseContext, WeslParseError, WeslParseState, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, blankWeslParseState, childIdent, childScope, containsScope, debugContentsToString, emptyScope, errorHighlight, filterMap, findMap, findRefsToBindingStructs, findValidRootDecls, flatImports, groupBy, grouped, identToString, isGlobal, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, multiKeySet, nextIdentId, noSuffix, normalize, normalizeModuleName, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, scan, scopeToString, scopeToStringLong, syntheticWeslParseState, transformBindingReference, transformBindingStruct, underscoreMangle };
|