Programme.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Компилятор языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package ru.malik.elaborarer.avtoo.lang;

import avt.io.*;
import avt.util.*;
import platform.independent.filesystem.*;
import platform.independent.streamformat.*;

public abstract class Programme(Object, AVTOOConstants)
{
    private static int comparisonOrder(Type type) { return type instanceof ArrayType ? 3 : type instanceof ClassType ? 2 : type instanceof PrimitiveType ? 1 : 0; }

    private boolean fldConstantFactoryIsUnlocked;
    private Package fldLanguagePackage;
    private Package fldSystemPackage;
    private final int fldPointerSize;
    private final PrimitiveType[] fldPrimitives;
    private final ClassTypeArray fldClassesArray;
    private final ArrayTypeArray fldArraysArray;
    private final TypeArray fldTypesArray;
    private final PackageArray fldPackagesArray;
    private final LibraryArray fldLibrariesArray;
    private final NullType fldNullType;
    private final Hashtable fldTypesTable;
    private final Hashtable fldPackagesTable;
    private final Hashtable fldLibrariesTable;
    private final ConstantFactory fldConstantFactory;

    protected (int pointerSize) {
        fldPointerSize = pointerSize == BITS32 ? BITS32 : BITS64;
        fldPrimitives = new PrimitiveType[PRIMITIVES_LENGTH];
        fldClassesArray = new ClassTypeArray();
        fldArraysArray = new ArrayTypeArray();
        fldTypesArray = new TypeArray();
        fldPackagesArray = new PackageArray();
        fldLibrariesArray = new LibraryArray();
        fldNullType = new NullType();
        fldTypesTable = new Hashtable();
        fldPackagesTable = new Hashtable();
        fldLibrariesTable = new Hashtable();
        fldConstantFactory = new ConstantFactory();
    }

    public abstract void compile() throws IOException, CompilerException;

    public Library createLibrary(FileSystem fileSystem, String directoryPath, boolean application) {
        Library result = newLibrary(fileSystem, directoryPath, application);
        if(result == null) result = new Library(this, fileSystem, directoryPath, application);
        appendLibrary(result);
        return result;
    }

    public final boolean isConstantFactoryUnlocked() { return fldConstantFactoryIsUnlocked; }

    public final ConstantFactory getConstantFactory() {
        if(!fldConstantFactoryIsUnlocked)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.can-not-create.constants"));
        }
        return fldConstantFactory;
    }

    public final Library getLibrary(FileSystem fileSystem, String directoryPath) { return (Library) fldLibrariesTable[new ProgrammeLibraryKey(fileSystem, directoryPath)]; }

    public final Package getPackage(String specialCanonicalName) { return (Package) fldPackagesTable[specialCanonicalName != null ? specialCanonicalName : ""]; }

    public final Package getPackage(String specialCanonicalName, boolean ignoreCase) {
        if(specialCanonicalName == null)
        {
            specialCanonicalName = "";
        }
        if(!ignoreCase)
        {
            return (Package) fldPackagesTable[specialCanonicalName];
        }
        for(Package[] packages = fldPackagesArray.array, int index = packages.length; index-- > 0; )
        {
            Package pack = packages[index];
            if(specialCanonicalName.equalsIgnoreCase(pack.specialCanonicalName)) return pack;
        }
        return null;
    }

    public final Package getSystemPackage() { return fldSystemPackage; }

    public final Package getLanguagePackage() { return fldLanguagePackage; }

    public final Type getType(String specialCanonicalName) {
        return TYPENAME_NULL.equals(specialCanonicalName) ? fldNullType : (Type) fldTypesTable[specialCanonicalName != null ? specialCanonicalName : ""];
    }

    public final NullType getNullType() { return fldNullType; }

    public final PrimitiveType getPrimitiveType(int kind) { return kind < VOID || kind >= VOID + PRIMITIVES_LENGTH ? null : fldPrimitives[kind - VOID]; }

    public final ClassType getClassType(String specialCanonicalName) {
        Object type = fldTypesTable[specialCanonicalName != null ? specialCanonicalName : ""];
        return !(type instanceof ClassType) ? null : (ClassType) type;
    }

    public final ArrayType getArrayType(Type componentType) {
        if(componentType == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "componentType" }));
        }
        if(componentType.isVoid() || componentType.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.illegal"));
        }
        if(componentType.parentProgramme != this)
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.not-same-programme"));
        }
        if((!(componentType instanceof ArrayType) ? 0 : ((ArrayType) componentType).dimensionsCount) > LIMIT_DIMENSIONS_COUNT - 1)
        {
            throw new IllegalArrayDimensionsCountException(package.getResourceString("array.dimensions-count"));
        }
        Object type = fldTypesTable[componentType.specialCanonicalName + "[]"];
        return !(type instanceof ArrayType) ? null : (ArrayType) type;
    }

    public final ArrayType getArrayType(Type componentType, int dimensionsCount) {
        if(componentType == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "componentType" }));
        }
        if(componentType.isVoid() || componentType.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.illegal"));
        }
        if(componentType.parentProgramme != this)
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.not-same-programme"));
        }
        if(dimensionsCount < 1 || dimensionsCount > (!(componentType instanceof ArrayType) ? LIMIT_DIMENSIONS_COUNT : LIMIT_DIMENSIONS_COUNT - ((ArrayType) componentType).dimensionsCount))
        {
            throw new IllegalArrayDimensionsCountException(package.getResourceString("array.dimensions-count"));
        }
        StringBuilder specialCanonicalName = new StringBuilder(450) + componentType.specialCanonicalName;
        do specialCanonicalName + "[]"; while(--dimensionsCount > 0);
        Object type = fldTypesTable[specialCanonicalName.toString()];
        return !(type instanceof ArrayType) ? null : (ArrayType) type;
    }

    public final ArrayType acquireArrayType(Type componentType) {
        if(componentType == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "componentType" }));
        }
        if(componentType.isVoid() || componentType.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.illegal"));
        }
        if(componentType.parentProgramme != this)
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.not-same-programme"));
        }
        if((!(componentType instanceof ArrayType) ? 0 : ((ArrayType) componentType).dimensionsCount) > LIMIT_DIMENSIONS_COUNT - 1)
        {
            throw new IllegalArrayDimensionsCountException(package.getResourceString("array.dimensions-count"));
        }
        Type result = null;
        synchronized(fldPrimitives)
        {
            if((result = (Type) fldTypesTable[componentType.specialCanonicalName + "[]"]) == null) result = createArrayType(componentType);
        }
        if(!(result instanceof ArrayType))
        {
            throw new IllegalProgrammeStateException(String.format(package.getResourceString("type.not-a-array"), new Object[] { result.specialCanonicalName }));
        }
        return (ArrayType) result;
    }

    public final ArrayType acquireArrayType(Type componentType, int dimensionsCount) {
        if(componentType == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "componentType" }));
        }
        if(componentType.isVoid() || componentType.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.illegal"));
        }
        if(componentType.parentProgramme != this)
        {
            throw new IllegalArgumentException(package.getResourceString("array.components-type.not-same-programme"));
        }
        if(dimensionsCount < 1 || dimensionsCount > (!(componentType instanceof ArrayType) ? LIMIT_DIMENSIONS_COUNT : LIMIT_DIMENSIONS_COUNT - ((ArrayType) componentType).dimensionsCount))
        {
            throw new IllegalArrayDimensionsCountException(package.getResourceString("array.dimensions-count"));
        }
        Type result = null;
        synchronized(fldPrimitives)
        {
            Hashtable table = fldTypesTable;
            StringBuilder specialCanonicalName = new StringBuilder(450) + componentType.specialCanonicalName;
            do
            {
                if((result = (Type) table[(specialCanonicalName + "[]").toString()]) == null) result = createArrayType(componentType);
                componentType = result;
            } while(--dimensionsCount > 0);
        }
        if(!(result instanceof ArrayType))
        {
            throw new IllegalProgrammeStateException(String.format(package.getResourceString("type.not-a-array"), new Object[] { result.specialCanonicalName }));
        }
        return (ArrayType) result;
    }

    public final int pointerSize { read = fldPointerSize }

    public final LibraryArray libraries { read = fldLibrariesArray }

    public final PackageArray packages { read = fldPackagesArray }

    public final TypeArray types { read = fldTypesArray }

    public final ArrayTypeArray arrays { read = fldArraysArray }

    public final ClassTypeArray classes { read = fldClassesArray }

    protected abstract void prefetchSupertypesForPrimitiveArray(ArrayType array);

    protected abstract void prefetchSupertypesForObjectArray(ArrayType array);

    protected abstract void prefetchSupertypesForReferenceArray(ArrayType array);

    protected abstract void createMembersForPrimitiveArray(ArrayType array);

    protected abstract void createMembersForObjectArray(ArrayType array);

    protected void appendLibrary(Library item) {
        if(item == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "item" }));
        }
        if(item.parentProgramme != this)
        {
            throw new IllegalArgumentException(package.getResourceString("adding-library.not-owned-by-programme"));
        }
        LibraryArray list = fldLibrariesArray;
        if(list.indexOf(item) >= 0)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("adding-library.already-added"));
        }
        list.append(item);
        fldLibrariesTable.operator []=(new ProgrammeLibraryKey(item), item);
    }

    protected void appendPackage(Package item) {
        if(item == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "item" }));
        }
        if(item.parentProgramme != this)
        {
            throw new IllegalArgumentException(package.getResourceString("adding-package.not-owned-by-programme"));
        }
        PackageArray list = fldPackagesArray;
        if(list.indexOf(item) >= 0)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("adding-package.already-added"));
        }
        DataHolder key = item.specialCanonicalName;
        list.append(item);
        fldPackagesTable[key] = item;
        if(key.isEmpty()) fldSystemPackage = item;
        if(key.equals(PACKNAME_LANG)) fldLanguagePackage = item;
    }

    protected void appendType(Type item) {
        if(item == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "item" }));
        }
        if(item.parentProgramme != this)
        {
            throw new IllegalArgumentException(package.getResourceString("adding-type.not-owned-by-programme"));
        }
        TypeArray list = fldTypesArray;
        if(list.indexOf(item) >= 0)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("adding-type.already.added"));
        }
        list.append(item);
        fldTypesTable[item.specialCanonicalName] = item;
        if(item instanceof ArrayType)
        {
            fldArraysArray.append((ArrayType) item);
            return;
        }
        if(item instanceof ClassType)
        {
            fldClassesArray.append((ClassType) item);
            return;
        }
        if(item instanceof PrimitiveType)
        {
            PrimitiveType primitive = (PrimitiveType) item;
            fldPrimitives[primitive.kind - VOID] = primitive;
        }
    }

    protected int compareTypes(Type type0, Type type1) {
        /* type0 - type1 */
        /* type0 > type1 ?  1 */
        /* type0 < type1 ? -1 */
        int order0 = comparisonOrder(type0);
        int order1 = comparisonOrder(type1);
        if(order0 != order1)
        {
            return order0 - order1;
        }
        switch(order0)
        {
        case 1:
            return type0.kind - type1.kind;
        case 2:
            boolean isHelper0 = type0.isHelper();
            boolean isHelper1 = type1.isHelper();
            return
                type0 == type1 || isHelper0 && isHelper1 ? Comparable.EQUALS :
                isHelper0 ? 1 :
                isHelper1 ? -1 :
                type0.isAssignableFrom(type1) ? -1 :
                type1.isAssignableFrom(type0) ? 1 :
                Comparable.INDEFINITE
            ;
        case 3:
            ArrayType array0 = (ArrayType) type0;
            ArrayType array1 = (ArrayType) type1;
            if(array0.isSuperclass(array1)) return 1;
            if(array1.isSuperclass(array0)) return -1;
            Type component0 = array0.componentType;
            Type component1 = array1.componentType;
            order0 = comparisonOrder(component0);
            order1 = comparisonOrder(component1);
            return
                order0 != order1 ? order0 - order1 :
                order0 == 1 ? component0.kind - component1.kind :
                array0.dimensionsCount - array1.dimensionsCount
            ;
        }
        return Comparable.INDEFINITE;
    }

    protected String[] essentialTypesNames() {
        return new String[] {
            PACKNAME_LANG + "." + TYPENAME_CLASS,
            PACKNAME_LANG + "." + TYPENAME_OBJECT,
            PACKNAME_LANG + "." + TYPENAME_STRING,
            PACKNAME_LANG + "." + TYPENAME_STRUCT,
            PACKNAME_LANG + "." + TYPENAME_PACKAGE,
            PACKNAME_LANG + "." + TYPENAME_THROWABLE
        };
    }

    protected Local createLocal(boolean isFinal, Type type, String specialSimpleName, Constant value, Source source, int declarationPosition) {
        Local result = newLocal(isFinal, type, specialSimpleName, value, source, declarationPosition);
        if(result == null) result = new Local(isFinal, type, specialSimpleName, value, source, declarationPosition);
        return result;
    }

    protected Library newLibrary(FileSystem fileSystem, String directoryPath, boolean application) { return null; }

    protected Source newSource(Library parentLibrary, String relativePath, String type) { return null; }

    protected Package newPackage(Library parentLibrary, int visibility, String specialCanonicalName, Source source, int declarationPosition, int documentationPosition) { return null; }

    protected ClassType newClassType(Package parentPackage, int attributes, String specialSimpleName, Source source, int declarationPosition, int documentationPosition, String outputPath) {
        return null;
    }

    protected ArrayType newArrayType(Type componentType) { return null; }

    protected Union newNestedUnion(AllocatableFactory parentItem, int declarationPosition, int documentationPosition) { return null; }

    protected Struct newNestedStruct(AllocatableFactory parentItem, int declarationPosition, int documentationPosition) { return null; }

    protected Field newStructField(AllocatableFactory parentItem, Type type, int capacity, String specialSimpleName, int declarationPosition, int documentationPosition) { return null; }

    protected Field newStructField(ClassType parentType, int structOffset, Type type, int capacity, String specialSimpleName, int declarationPosition, int documentationPosition) { return null; }

    protected Field newClassField(ClassType parentType, int attributes, Type type, String specialSimpleName, int declarationPosition, int documentationPosition) { return null; }

    protected ClassInit newStaticBlock(ClassType parentType, int attributes, int declarationPosition, int documentationPosition) { return null; }

    protected InstInit newConstructor(ClassType parentType, int attributes, Local[] arguments, int declarationPosition, int documentationPosition) { return null; }

    protected Method newMethod(ClassType parentType, int attributes, Type type, String specialSimpleName, Local[] arguments, int declarationPosition, int documentationPosition) { return null; }

    protected Operator newOperator(ClassType parentType, int attributes, Type type, int kind, Local[] arguments, int declarationPosition, int documentationPosition) { return null; }

    protected Property newProperty(ClassType parentType, int attributes, Type type, String specialSimpleName, int declarationPosition, int documentationPosition) { return null; }

    protected Local newLocal(boolean isFinal, Type type, String specialSimpleName, Constant value, Source source, int declarationPosition) { return null; }

    protected Code newCode(Callable parentCallable) { return null; }

    protected Node newNode(Code parentCode) { return null; }

    protected final void sortTypes() {
        Type[] types = fldTypesArray.array;
        int length = types.length;
        int limit = length - 1;
        for(int tpi = 0; tpi < limit; tpi++) for(Type type0 = types[tpi], int tpj = tpi + 1; tpj < length; tpj++)
        {
            Type type1 = types[tpj];
            if(compareTypes(type0, type1) > 0)
            {
                types[tpj] = type0;
                types[tpj = tpi] = type0 = type1;
            }
        }
    }

    protected final void initSubtypes() {
        initSubtypes(fldClassesArray.array);
        initSubtypes(fldArraysArray.array);
    }

    protected final void createArrayTypes() {
        ArrayTypeArray list = fldArraysArray;
        if(list.length > 0)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.already-created.main-arrays-types"));
        }
        Package packageSystem = fldSystemPackage;
        if(packageSystem == null)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.not-created.system-package"));
        }
        Package packageLanguage = fldLanguagePackage;
        if(packageLanguage == null)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.not-created.language-package"));
        }
        ClassType classObject = getClassType(PACKNAME_LANG + "." + TYPENAME_OBJECT);
        if(classObject == null)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.not-created.object-type"));
        }
        PrimitiveType[] primitives = fldPrimitives;
        for(int kind = BOOLEAN; kind < VOID + PRIMITIVES_LENGTH; kind++) if(isPrimitiveKind(kind) && primitives[kind - VOID] == null)
        {
            throw new IllegalProgrammeStateException(String.format(
                package.getResourceString("programme.not-created.primitive-type"), new Object[] { PrimitiveType.kindToSpecialSimpleName(kind) }
            ));
        }
        /* разблокировка возможности создания констант */
        if(getClassType(PACKNAME_LANG + "." + TYPENAME_STRING) == null)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.not-created.string-type"));
        }
        if(getClassType(PACKNAME_LANG + "." + TYPENAME_CLASS) == null)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.not-created.class-type"));
        }
        if(getClassType(PACKNAME_LANG + "." + TYPENAME_PACKAGE) == null)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.not-created.package-type"));
        }
        fldConstantFactory.loadDataFrom(this);
        fldConstantFactoryIsUnlocked = true;
        /* создание массивов */
        for(int kind = BOOLEAN; kind < VOID + PRIMITIVES_LENGTH; kind++) if(isPrimitiveKind(kind))
        {
            PrimitiveType primitive = primitives[kind - VOID];
            ArrayType array = newArrayType(primitive);
            if(array == null) array = new ArrayType(primitive);
            packageSystem.appendChildItem(array);
            appendType(array);
            array.makeCompilable();
        }
        {
            ArrayType array = newArrayType(classObject);
            if(array == null) array = new ArrayType(classObject);
            packageLanguage.appendChildItem(array);
            appendType(array);
            array.makeCompilable();
        }
        /* определение супертипов массивов */
        for(ArrayType[] arrays = list.array, int length = arrays.length, int index = 0; index < length; index++)
        {
            ArrayType array = arrays[index];
            if(array.componentType.getClass() == PrimitiveType.class)
            {
                prefetchSupertypesForPrimitiveArray(array);
                continue;
            }
            prefetchSupertypesForObjectArray(array);
        }
    }

    protected final void createPrimitiveTypes() {
        Package systemPackage = fldSystemPackage;
        if(systemPackage == null)
        {
            throw new IllegalProgrammeStateException(package.getResourceString("programme.not-created.system-package"));
        }
        PrimitiveType[] primitives = fldPrimitives;
        for(int kind = VOID; kind < VOID + PRIMITIVES_LENGTH; kind++) if(isPrimitiveKind(kind) && primitives[kind - VOID] != null)
        {
            throw new IllegalProgrammeStateException(String.format(
                package.getResourceString("programme.already-created.primitive-type"), new Object[] { PrimitiveType.kindToSpecialSimpleName(kind) }
            ));
        }
        /* создание примитивов */
        for(int kind = VOID; kind < VOID + PRIMITIVES_LENGTH; kind++) if(isPrimitiveKind(kind))
        {
            PrimitiveType primitive = new PrimitiveType(systemPackage, kind);
            systemPackage.appendChildItem(primitive);
            appendType(primitive);
        }
    }

    protected final void createMembersForArrayTypes() {
        for(ClassType objectType = getClassType(PACKNAME_LANG + "." + TYPENAME_OBJECT), ArrayType[] arrays = fldArraysArray.array, int length = arrays.length, int index = 0; index < length; index++)
        {
            ArrayType array = arrays[index];
            Type component = array.componentType;
            if(component.getClass() == PrimitiveType.class)
            {
                createMembersForPrimitiveArray(array);
                continue;
            }
            if(component == objectType)
            {
                createMembersForObjectArray(array);
                continue;
            }
            break;
        }
    }

    protected final void checkEssentialTypesPresence() throws CompilerException {
        for(String[] names = essentialTypesNames(), int length = names == null ? 0 : names.length, int index = 0; index < length; index++)
        {
            String name = names[index];
            if(getType(name) == null)
            {
                throw new CompilerException(String.format(package.getResourceString("essential-type.not-found"), new Object[] { name }));
            }
        }
    }

    private void initSubtypes(ClassType[] classes) {
        for(int length = classes.length, int index = 0; index < length; index++) classes[index].initSubtypes();
    }

    private ArrayType createArrayType(Type componentType) {
        ArrayType result = newArrayType(componentType);
        if(result == null) result = new ArrayType(componentType);
        componentType.parentPackage.appendChildItem(result);
        appendType(result);
        prefetchSupertypesForReferenceArray(result);
        result.appendImpliedSuperservices();
        return result;
    }
}

final class ProgrammeLibraryKey(Object)
{
    private final int fldHashCode;
    private final long fldHashCodeAsLong;
    private final long2 fldHashCodeAsLong2;
    private final long4 fldHashCodeAsLong4;
    private final String fldDirectoryPath;
    private final FileSystem fldFileSystem;

    public (Library library): this(library.fileSystem, library.directoryPath) {  }

    public (FileSystem fileSystem, String directoryPath) {
        if(fileSystem == null) fileSystem = Platform.instance.localFileSystem;
        if(directoryPath == null || directoryPath.isEmpty()) directoryPath = "/";
        long2 fileSystemHash = fileSystem.hashCodeAsLong2();
        long2 directoryPathHash = directoryPath.hashCodeAsLong2();
        fldHashCode = fileSystem.hashCode() ^ directoryPath.hashCode();
        fldHashCodeAsLong = fileSystem.hashCodeAsLong() ^ directoryPath.hashCodeAsLong();
        fldHashCodeAsLong2 = fileSystemHash ^ directoryPathHash;
        fldHashCodeAsLong4 = fileSystemHash + directoryPathHash * Math.J;
        fldDirectoryPath = directoryPath;
        fldFileSystem = fileSystem;
    }

    public boolean equals(Object anot) {
        if(anot == this) return true;
        if(!(anot instanceof ProgrammeLibraryKey)) return false;
        ProgrammeLibraryKey lkey = (ProgrammeLibraryKey) anot;
        return lkey.fldFileSystem == fldFileSystem && lkey.fldDirectoryPath.equals(fldDirectoryPath);
    }

    public int hashCode() { return fldHashCode; }

    public long hashCodeAsLong() { return fldHashCodeAsLong; }

    public long2 hashCodeAsLong2() { return fldHashCodeAsLong2; }

    public long4 hashCodeAsLong4() { return fldHashCodeAsLong4; }
}