@@ -173,6 +173,8 @@ const bannedTokens = new Set([
173173 'with' ,
174174 'writeonly' ,
175175 'yield' ,
176+ // Keywords that should be reserved
177+ 'sampler' ,
176178] ) ;
177179
178180export interface NameRegistry {
@@ -181,8 +183,9 @@ export interface NameRegistry {
181183 * in the lifetime of a single resolution process.
182184 * Should append "_" to primer, followed by some id.
183185 * @param primer Used in the generation process, makes the identifier more recognizable.
186+ * @param global Whether the name should be registered in the global scope (true), or in the current function scope (false)
184187 */
185- makeUnique ( primer ? : string ) : string ;
188+ makeUnique ( primer : string | undefined , global : boolean ) : string ;
186189
187190 /**
188191 * Creates a valid WGSL identifier.
@@ -196,6 +199,9 @@ export interface NameRegistry {
196199 * makeValid("_"); // ERROR (too difficult to make valid to care)
197200 */
198201 makeValid ( primer : string ) : string ;
202+
203+ pushFunctionScope ( ) : void ;
204+ popFunctionScope ( ) : void ;
199205}
200206
201207function sanitizePrimer ( primer : string | undefined ) {
@@ -229,45 +235,78 @@ export function isValidIdentifier(ident: string): boolean {
229235}
230236
231237abstract class NameRegistryImpl implements NameRegistry {
232- abstract makeUnique ( primer ?: string ) : string ;
238+ abstract getUniqueVariant ( base : string ) : string ;
239+
240+ readonly #usedNames: Set < string > ;
241+ readonly #usedFunctionScopeNamesStack: Set < string > [ ] ;
242+
243+ constructor ( ) {
244+ this . #usedNames = new Set < string > ( bannedTokens ) ;
245+ this . #usedFunctionScopeNamesStack = [ ] ;
246+ }
247+
248+ get usedFunctionScopeNames ( ) : Set < string > | undefined {
249+ return this
250+ . #usedFunctionScopeNamesStack[
251+ this . #usedFunctionScopeNamesStack. length - 1
252+ ] ;
253+ }
254+
255+ makeUnique ( primer : string | undefined , global : boolean ) : string {
256+ const sanitizedPrimer = sanitizePrimer ( primer ) ;
257+ const name = this . getUniqueVariant ( sanitizedPrimer ) ;
258+
259+ if ( global ) {
260+ this . #usedNames. add ( name ) ;
261+ } else {
262+ this . usedFunctionScopeNames ?. add ( name ) ;
263+ }
264+
265+ return name ;
266+ }
233267
234268 makeValid ( primer : string ) : string {
235- if ( isValidIdentifier ( primer ) ) {
269+ if ( isValidIdentifier ( primer ) && ! this . #usedNames. has ( primer ) ) {
270+ this . usedFunctionScopeNames ?. add ( primer ) ;
236271 return primer ;
237272 }
238- return this . makeUnique ( primer ) ;
273+ return this . makeUnique ( primer , false ) ;
239274 }
240- }
241275
242- export class RandomNameRegistry extends NameRegistryImpl {
243- private lastUniqueId = 0 ;
276+ isUsed ( name : string ) : boolean {
277+ return this . #usedNames. has ( name ) ||
278+ ! ! this . usedFunctionScopeNames ?. has ( name ) ;
279+ }
244280
245- makeUnique ( primer ?: string | undefined ) : string {
246- const sanitizedPrimer = sanitizePrimer ( primer ) ;
281+ pushFunctionScope ( ) : void {
282+ this . #usedFunctionScopeNamesStack. push ( new Set < string > ( ) ) ;
283+ }
247284
248- return `${ sanitizedPrimer } _${ this . lastUniqueId ++ } ` ;
285+ popFunctionScope ( ) : void {
286+ this . #usedFunctionScopeNamesStack. pop ( ) ;
249287 }
250288}
251289
252- export class StrictNameRegistry extends NameRegistryImpl {
253- /**
254- * Allows to provide a good fallback for instances of the
255- * same function that are bound to different slot values.
256- */
257- private readonly _usedNames = new Set < string > ( bannedTokens ) ;
290+ export class RandomNameRegistry extends NameRegistryImpl {
291+ #lastUniqueId = 0 ;
258292
259- // TODO: optimize this with a map
260- makeUnique ( primer ?: string | undefined ) : string {
261- const sanitizedPrimer = sanitizePrimer ( primer ) ;
293+ getUniqueVariant ( base : string ) : string {
294+ let name = `${ base } _${ this . #lastUniqueId++ } ` ;
295+ while ( this . isUsed ( name ) ) {
296+ name = `${ base } _${ this . #lastUniqueId++ } ` ;
297+ }
298+ return name ;
299+ }
300+ }
262301
302+ export class StrictNameRegistry extends NameRegistryImpl {
303+ getUniqueVariant ( base : string ) : string {
263304 let index = 0 ;
264- let label = sanitizedPrimer ;
265- while ( this . _usedNames . has ( label ) ) {
305+ let name = base ;
306+ while ( this . isUsed ( name ) ) {
266307 index ++ ;
267- label = `${ sanitizedPrimer } _${ index } ` ;
308+ name = `${ base } _${ index } ` ;
268309 }
269-
270- this . _usedNames . add ( label ) ;
271- return label ;
310+ return name ;
272311 }
273312}
0 commit comments