package org.shedlang.compiler.backends; import org.pcollections.Empty; import org.pcollections.PSet; import java.util.Optional; import java.util.function.Predicate; public record NameAllocator(PSet existingNames) { public static NameAllocator empty() { return new NameAllocator<>(Empty.set()); } public Result allocateName( TPrefix prefix, Optional name ) { var fullName = allocateName(existingNames::contains, prefix, name); var newAllocator = new NameAllocator(existingNames.plus(fullName)); return new Result<>(fullName, newAllocator); } public Result allocateFixedName(TPrefix prefix, String name) { var fullName = allocateFixedName(existingNames::contains, prefix, name); var newAllocator = new NameAllocator(existingNames.plus(fullName)); return new Result<>(fullName, newAllocator); } public static String allocateName( Predicate isUsed, TPrefix prefix, Optional name ) { var fullPrefix = prefix.toString(); if (name.isPresent()) { fullPrefix += "__" + name.get(); } var index = 0; while (true) { var fullName = fullPrefix + "__" + index; if (isUsed.test(fullName)) { index++; } else { return fullName; } } } public static String allocateFixedName(Predicate isUsed, TPrefix prefix, String name) { var fullName = prefix + "__" + name; if (isUsed.test(fullName)) { throw new RuntimeException("name is already allocated: " + fullName); } return fullName; } public record Result(String name, NameAllocator allocator) { } }