ClassType.avt

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

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

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

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

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

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

package ru.malik.elaborarer.avtoo.lang;

import avt.lang.array.*;

public class ClassType(ReferenceType, Cloneable, Measureable, ObjectArray, AllocatableFactory, AVTOOConstants)
{
    private boolean fldStructMarked;
    private int fldNativeCallablesCounter;
    private int fldStructSize;
    private int fldInstanceSize;
    private int fldHelperForPosition;
    private int fldSuperclassPosition;
    private int fldSuperservicesLength;
    private int fldUserMembersInsertionPosition;
    private int[] fldSuperservicesPositions;
    private Callable[] fldVirtualCallables;
    private Callable[] fldServiceCallables;
    private ClassType[] fldSuperservicesTypes;
    private ClassType fldSuperclassType;
    private ClassType fldHelperForType;
    private InstInit fldDefaultConstructor;
    private ClassInit fldStaticBlock;
    private FieldsMap fldFieldsMap;
    private Local fldThisArgument;
    private final String fldOutputPath;
    private final ClassTypeArray fldHelpers;
    private final ClassTypeArray fldSubtypes;

    public (Package parentPackage, int attributes, String specialSimpleName, Source source, int declarationPosition, int documentationPosition, String outputPath):
        super(parentPackage, attributes, specialSimpleName, source, declarationPosition, documentationPosition) {
        boolean isHelper = isHelper();
        fldHelperForPosition = -1;
        fldSuperclassPosition = -1;
        fldThisArgument = isHelper ? null : createThisArgument();
        fldOutputPath = outputPath;
        fldHelpers = isHelper ? null : new ClassTypeArray();
        fldSubtypes = (attributes &= MASK_TYPE | ATTR_FINAL) != 0 && attributes != ATTR_STRUCT ? null : new ClassTypeArray();
    }

    public boolean isAssignableFrom(Type anot) {
        if(anot == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "anot" }));
        }
        return anot == this || anot.isNull() || anot instanceof ClassType && (isService() ? ((ClassType) anot).isSuperservice(this) : ((ClassType) anot).isSuperclass(this));
    }

    public boolean isCompatibleWith(Type anot) {
        if(anot == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "anot" }));
        }
        if(anot.isNull())
        {
            return true;
        }
        if(!(anot instanceof ClassType))
        {
            return false;
        }
        boolean thisIsFinal = isFinal();
        boolean thisIsService = isService();
        boolean anotIsFinal = anot.isFinal();
        boolean anotIsService = anot.isService();
        ClassType type = (ClassType) anot;
        ClassType thisSuperclass = fldSuperclassType;
        ClassType anotSuperclass = type.fldSuperclassType;
        return thisIsService ? (
            anotIsService ? (
                thisSuperclass == anotSuperclass ||
                thisSuperclass.isSuperclass(anotSuperclass) ||
                anotSuperclass.isSuperclass(thisSuperclass)
            ) : (
                anotIsFinal ? (
                    type.isSuperservice(this)
                ) : (
                    thisSuperclass == type ||
                    thisSuperclass.isSuperclass(type) ||
                    type.isSuperclass(thisSuperclass)
                )
            )
        ) : (
            anotIsService ? (
                thisIsFinal ? (
                    isSuperservice(type)
                ) : (
                    this == anotSuperclass ||
                    isSuperclass(anotSuperclass) ||
                    anotSuperclass.isSuperclass(this)
                )
            ) : (
                this == type ||
                isSuperclass(type) ||
                type.isSuperclass(this)
            )
        );
    }

    public boolean isClass() { return (attributes & MASK_TYPE) == 0; }

    public boolean isStruct() { return (attributes & MASK_TYPE) == ATTR_STRUCT; }

    public boolean isService() { return (attributes & (ATTR_PRIMITIVE | ATTR_SERVICE)) == ATTR_SERVICE; }

    public boolean isInterface() { return (attributes & MASK_TYPE) == ATTR_INTERFACE; }

    public boolean isHelper() { return (attributes & (MASK_BINDING | MASK_TYPE)) == (ATTR_FINAL | ATTR_SERVICE); }

    public ClassType getRealType() { return !isHelper() ? this : fldHelperForType; }

    public Union createNestedUnion(int declarationPosition, int documentationPosition) {
        if(!isStruct())
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.not-a-struct"));
        }
        return AllocatableFactory.super.createNestedUnion(declarationPosition, documentationPosition);
    }

    public Struct createNestedStruct(int declarationPosition, int documentationPosition) {
        if(!isStruct())
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.not-a-struct"));
        }
        return AllocatableFactory.super.createNestedStruct(declarationPosition, documentationPosition);
    }

    public Field createStructField(Type type, int capacity, String specialSimpleName, int declarationPosition, int documentationPosition) {
        if(!isStruct())
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.not-a-struct"));
        }
        return AllocatableFactory.super.createStructField(type, capacity, specialSimpleName, declarationPosition, documentationPosition);
    }

    public void removeStaticBlock() {
        Member member = fldStaticBlock;
        if(member != null)
        {
            if(!member.isSynthetic()) fldUserMembersInsertionPosition--;
            removeChildItem(member);
        }
    }

    public void initHelperFor(ClassType target, int position) {
        if(!isHelper())
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.can-not-init-targettype"));
        }
        if(fldHelperForType != null)
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.initialized-targettype"));
        }
        if(target == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "target" }));
        }
        if(target.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("target-type.not-same-programme"));
        }
        if(target.isHelper())
        {
            throw new IllegalArgumentException(package.getResourceString("target-type.is-a-helper"));
        }
        fldHelperForPosition = position;
        fldHelperForType = target;
        fldThisArgument = target.fldThisArgument;
        target.fldHelpers.append(this);
    }

    public void initSuperclass(ClassType superclass, int position) {
        if(isHelper())
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.can-not-init-superclass"));
        }
        if(fldSuperclassType != null)
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.initialized-superclass"));
        }
        if(superclass == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "superclass" }));
        }
        if(superclass.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("superclass.not-same-programme"));
        }
        if(superclass.isHelper())
        {
            throw new IllegalArgumentException(package.getResourceString("superclass.is-a-helper"));
        }
        if(superclass.isService())
        {
            throw new IllegalArgumentException(package.getResourceString("superclass.is-a-service"));
        }
        fldSuperclassPosition = position;
        fldSuperclassType = superclass;
    }

    public void appendSuperservice(ClassType superservice, int position) {
        if(isHelper())
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.can-not-add-superservice"));
        }
        if(superservice == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "superservice" }));
        }
        if(superservice.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("superservice.not-same-programme"));
        }
        if(superservice.isHelper())
        {
            throw new IllegalArgumentException(package.getResourceString("superservice.is-a-helper"));
        }
        if(!superservice.isService())
        {
            throw new IllegalArgumentException(package.getResourceString("superservice.not-a-service"));
        }
        int length = fldSuperservicesLength;
        ClassType[] types = fldSuperservicesTypes;
        if(Array.indexOf(superservice, types, 0, length) >= 0)
        {
            throw new IllegalArgumentException(String.format(package.getResourceString("class-type.added-superservice"), new Object[] { superservice }));
        }
        int[] poses = fldSuperservicesPositions;
        if(types == null)
        {
            fldSuperservicesPositions = poses = new int[0x0f];
            fldSuperservicesTypes = types = new ClassType[0x0f];
        }
        else if(length == types.length)
        {
            if(length == Int.MAX_VALUE)
            {
                throw new BufferTooLargeError(avt.lang.package.getResourceString("!error.buffer-too-large"));
            }
            int capacity = length << 1 | 1;
            Array.copy(poses, 0, fldSuperservicesPositions = poses = new int[capacity], 0, length);
            Array.copy(types, 0, fldSuperservicesTypes = types = new ClassType[capacity], 0, length);
        }
        poses[length] = position;
        types[length++] = superservice;
        fldSuperservicesLength = length;
    }

    public void appendImpliedSuperservices() {
        if(isHelper()) return;
        int tindex = -1;
        int tlength = fldSuperservicesLength;
        int[] poses = fldSuperservicesPositions;
        ClassType[] types = fldSuperservicesTypes;
        ClassType current = fldSuperclassType;
        if(current == null && tlength > 0)
        {
            current = types[0];
            tindex = 1;
        }
        while(current != null)
        {
            int slength = current.fldSuperservicesLength;
            ClassType[] supers = current.fldSuperservicesTypes;
            for(int sindex = 0; sindex < slength; sindex++)
            {
                ClassType superservice = supers[sindex];
                if(Array.indexOf(superservice, types, 0, tlength) < 0)
                {
                    if(types == null)
                    {
                        fldSuperservicesPositions = poses = new int[0x0f];
                        fldSuperservicesTypes = types = new ClassType[0x0f];
                    }
                    else if(tlength == types.length)
                    {
                        if(tlength == Int.MAX_VALUE)
                        {
                            throw new BufferTooLargeError(avt.lang.package.getResourceString("!error.buffer-too-large"));
                        }
                        int capacity = tlength << 1 | 1;
                        Array.copy(poses, 0, fldSuperservicesPositions = poses = new int[capacity], 0, tlength);
                        Array.copy(types, 0, fldSuperservicesTypes = types = new ClassType[capacity], 0, tlength);
                    }
                    poses[tlength] = -1;
                    types[tlength++] = superservice;
                }
            }
            if(tindex < 0 && (current = current.fldSuperclassType) == null)
            {
                tindex = 0;
            }
            if(tindex >= 0)
            {
                current = tindex >= tlength ? null : types[tindex];
                tindex++;
            }
        }
        fldSuperservicesLength = tlength;
    }

    public boolean isFreeThrowableType() {
        String name = specialCanonicalName;
        return
            name.equals(PACKNAME_LANG + "." + TYPENAME_ERROR) ||
            isSuperclass(PACKNAME_LANG + "." + TYPENAME_ERROR) ||
            name.equals(PACKNAME_LANG + "." + TYPENAME_RUNTIME_EXCEPTION) ||
            isSuperclass(PACKNAME_LANG + "." + TYPENAME_RUNTIME_EXCEPTION)
        ;
    }

    public Field createStructField(int structOffset, Type type, int capacity, String specialSimpleName, int declarationPosition, int documentationPosition) {
        if(!isStruct())
        {
            throw new IllegalClassTypeStateException(package.getResourceString("class-type.not-a-struct"));
        }
        if(structOffset < 0)
        {
            throw new IllegalArgumentException(package.getResourceString("negative.offset"));
        }
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        Programme programme = parentProgramme;
        if(type.parentProgramme != programme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        if(capacity > LIMIT_FIELD_LENGTH)
        {
            throw new IllegalArgumentException(String.format(package.getResourceString("field.length-too-large"), new Object[] { Int.toString(LIMIT_FIELD_LENGTH) }));
        }
        if(type.isVoid() || type.isNull() || (capacity <= 0 ? !type.isPrimitive() : !(type instanceof ArrayType) || !((ArrayType) type).componentType.isPrimitive()))
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-suitable.field"));
        }
        Field result = programme == null ? null : programme.newStructField(this, structOffset, type, capacity, specialSimpleName, declarationPosition, documentationPosition);
        if(result == null) result = new Field(this, structOffset, type, capacity, specialSimpleName, declarationPosition, documentationPosition);
        appendChildItem(result);
        return result;
    }

    public Field createClassField(int attributes, Type type, String specialSimpleName, int declarationPosition, int documentationPosition) {
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        Programme programme = parentProgramme;
        if(type.parentProgramme != programme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        if(type.isVoid() || type.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-suitable.field"));
        }
        Field result = programme == null ? null : programme.newClassField(this, attributes, type, specialSimpleName, declarationPosition, documentationPosition);
        if(result == null)
        {
            result = new Field(this, attributes, type, specialSimpleName, declarationPosition, documentationPosition);
        }
        if((attributes & ATTR_SYNTHETIC) != 0)
        {
            appendChildItem(result);
        } else
        {
            insertChildItem(result, fldUserMembersInsertionPosition++);
        }
        return result;
    }

    public ClassInit createStaticBlock(int attributes, int declarationPosition, int documentationPosition) {
        Programme programme = parentProgramme;
        ClassInit result = programme == null ? null : programme.newStaticBlock(this, attributes, declarationPosition, documentationPosition);
        if(result == null)
        {
            result = new ClassInit(this, attributes, declarationPosition, documentationPosition);
        }
        if((attributes & ATTR_SYNTHETIC) != 0)
        {
            appendChildItem(result);
        } else
        {
            insertChildItem(result, fldUserMembersInsertionPosition++);
        }
        return result;
    }

    public InstInit createConstructor(int attributes, Local[] arguments, int declarationPosition, int documentationPosition) {
        Programme programme = parentProgramme;
        InstInit result = programme == null ? null : programme.newConstructor(this, attributes, arguments, declarationPosition, documentationPosition);
        if(result == null)
        {
            result = new InstInit(this, attributes, arguments, declarationPosition, documentationPosition);
        }
        if((attributes & ATTR_SYNTHETIC) != 0)
        {
            appendChildItem(result);
        } else
        {
            insertChildItem(result, fldUserMembersInsertionPosition++);
        }
        return result;
    }

    public Method createMethod(int attributes, Type type, String specialSimpleName, Local[] arguments, int declarationPosition, int documentationPosition) {
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        Programme programme = parentProgramme;
        if(type.parentProgramme != programme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        if(type.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-suitable.method"));
        }
        Method result = programme == null ? null : programme.newMethod(this, attributes, type, specialSimpleName, arguments, declarationPosition, documentationPosition);
        if(result == null)
        {
            result = new Method(this, attributes, type, specialSimpleName, arguments, declarationPosition, documentationPosition);
        }
        if((attributes & ATTR_SYNTHETIC) != 0)
        {
            appendChildItem(result);
        } else
        {
            insertChildItem(result, fldUserMembersInsertionPosition++);
        }
        int position = specialSimpleName == null ? -1 : specialSimpleName.lastIndexOf('.');
        if(position >= 0) for(ProgrammeItem member = super.getChildItem(specialSimpleName.substring(0, position++)); member != null; member = member.nextItem) if(member instanceof Property)
        {
            String suffix = specialSimpleName.substring(position);
            if(suffix.equals(MEMBER_SUFFIX_READ))
            {
                ((Property) member).setReadSynthetic(result);
                break;
            }
            if(suffix.equals(MEMBER_SUFFIX_WRITE))
            {
                ((Property) member).setWriteSynthetic(result);
                break;
            }
            if(suffix.equals(MEMBER_SUFFIX_INDEX))
            {
                ((Property) member).setIndexSynthetic(result);
                break;
            }
            if(suffix.equals(MEMBER_SUFFIX_STORED))
            {
                ((Property) member).setStoredSynthetic(result);
            }
            break;
        }
        return result;
    }

    public Operator createOperator(int attributes, Type type, int kind, Local[] arguments, int declarationPosition, int documentationPosition) {
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        Programme programme = parentProgramme;
        if(type.parentProgramme != programme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        if(type.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-suitable.operator"));
        }
        Operator result = programme == null ? null : programme.newOperator(this, attributes, type, kind, arguments, declarationPosition, documentationPosition);
        if(result == null)
        {
            result = new Operator(this, attributes, type, kind, arguments, declarationPosition, documentationPosition);
        }
        if((attributes & ATTR_SYNTHETIC) != 0)
        {
            appendChildItem(result);
        } else
        {
            insertChildItem(result, fldUserMembersInsertionPosition++);
        }
        return result;
    }

    public Property createProperty(int attributes, Type type, String specialSimpleName, int declarationPosition, int documentationPosition) {
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        Programme programme = parentProgramme;
        if(type.parentProgramme != programme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        if(type.isVoid() || type.isNull())
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-suitable.property"));
        }
        Property result = programme == null ? null : programme.newProperty(this, attributes, type, specialSimpleName, declarationPosition, documentationPosition);
        if(result == null)
        {
            result = new Property(this, attributes, type, specialSimpleName, declarationPosition, documentationPosition);
        }
        if((attributes & ATTR_SYNTHETIC) != 0)
        {
            appendChildItem(result);
        } else
        {
            insertChildItem(result, fldUserMembersInsertionPosition++);
        }
        return result;
    }

    public final Member getChildItem(String specialSimpleName) { return (Member) super.getChildItem(specialSimpleName); }

    public final Member getChildItem(String specialSimpleName, boolean ignoreCase) { return (Member) super.getChildItem(specialSimpleName, ignoreCase); }

    public final void markupClass() {
        if(isHelper()) return;
        int instanceSize = 0;
        int vlength = 0;
        Callable[] vmethods;
        ClassType superclass = fldSuperclassType;
        FieldsMap fieldsMap;
        if(superclass == null)
        {
            fieldsMap = new FieldsMap();
            vmethods = new Callable[0x0f];
        } else
        {
            if((fieldsMap = superclass.fldFieldsMap) == null || (vmethods = superclass.fldVirtualCallables) == null)
            {
                throw new IllegalClassTypeStateException(package.getResourceString("superclass.has-no-markup"));
            }
            fieldsMap = fieldsMap.clone();
            instanceSize = superclass.fldInstanceSize;
            vlength = vmethods.length;
            Array.copy(vmethods, 0, vmethods = new Callable[vmethods.capacity], 0, vlength);
        }
        int mlength = length;
        Member[] members = new Member[mlength];
        for(int mindex = mlength; mindex-- > 0; )
        {
            ((ProgrammeItem[]) members)[mindex] = super.operator [](mindex);
        }
        /* разметка инстанции */
        {
            boolean isStruct = isStruct();
            for(int mindex = 0; mindex < mlength; mindex++)
            {
                Member member = members[mindex];
                if(!member.isStatic() && member instanceof Field)
                {
                    Field field = (Field) member;
                    String name = member.specialSimpleName;
                    if(!isStruct || field.type instanceof ReferenceType && name != null && !name.isEmpty())
                    {
                        int offsetAfter = field.computeInstanceOffset(instanceSize, fieldsMap);
                        if(instanceSize < offsetAfter) instanceSize = offsetAfter;
                    }
                }
            }
            if(isStruct) instanceSize += -instanceSize & 0x3f;
            fldFieldsMap = fieldsMap;
            fldInstanceSize = instanceSize;
        }
        /* разметка таблицы виртуальных методов */
        {
            for(int vindex = 0; vindex < vlength; vindex++)
            {
                Callable callable = vmethods[vindex];
                if(callable.isVisibleFrom(this, this))
                {
                    Callable overrides = (Callable) callable.overridesIn(this, Callable.TYPE);
                    if(overrides != null) (vmethods[vindex] = overrides).setVirtualIndex(vindex);
                }
            }
            ClassType[] stypes = getSubtypesStore();
            int slength = stypes == null ? 0 : stypes.length;
            if(slength > 0)
            {
                int olength = 0;
                Callable[] omethods = new Callable[mlength];
                for(int mindex = 0; mindex < mlength; mindex++)
                {
                    Member member = members[mindex];
                    if(!member.isStatic() && member instanceof Callable && member.visibility > PRIVATE && !member.isFinal() && !member.isSpecial())
                    {
                        Callable callable = (Callable) member;
                        if(callable.virtualIndex < 0) omethods[olength++] = callable;
                    }
                }
                for(int oindex = 0; oindex < olength; oindex++)
                {
                    for(Callable callable = omethods[oindex], int sindex = slength; sindex-- > 0; )
                    {
                        ClassType current = stypes[sindex];
                        if(callable.isVisibleFrom(current, current) && callable.overridesIn(current, Callable.TYPE) != null)
                        {
                            if(vlength == vmethods.capacity)
                            {
                                if(vlength == Int.MAX_VALUE)
                                {
                                    throw new BufferTooLargeError(avt.lang.package.getResourceString("!error.buffer-too-large"));
                                }
                                Array.copy(vmethods, 0, vmethods = new Callable[vlength << 1 | 1], 0, vlength);
                            }
                            (vmethods[vlength] = callable).setVirtualIndex(vlength++);
                            break;
                        }
                    }
                }
            }
            vmethods.length = vlength;
            fldVirtualCallables = vmethods;
        }
        /* разметка таблицы сервисных методов */
        if(isService())
        {
            int slength = 0;
            Callable[] smethods = new Callable[0x0f];
            for(int mindex = 0; mindex < mlength; mindex++)
            {
                Member member = members[mindex];
                if(!member.isStatic() && member instanceof Callable && member.visibility > PRIVATE && !member.isFinal() && !member.isSpecial())
                {
                    if(slength == smethods.capacity) Array.copy(smethods, 0, smethods = new Callable[slength << 1 | 1], 0, slength);
                    (smethods[slength] = (Callable) member).setServiceIndex(slength++);
                }
            }
            smethods.length = slength;
            fldServiceCallables = smethods;
        }
    }

    public final void markupStruct() {
        if(isHelper()) return;
        int structSize = 0;
        ClassType superclass = fldSuperclassType;
        if(superclass != null && superclass.isStruct())
        {
            if(!superclass.fldStructMarked)
            {
                throw new IllegalClassTypeStateException(package.getResourceString("superclass.has-no-markup"));
            }
            structSize = superclass.fldStructSize;
        }
        /* разметка структуры */
        if(isStruct())
        {
            for(int mlength = length, int mindex = 0; mindex < mlength; mindex++)
            {
                Member member = (Member) super.operator [](mindex);
                if(!member.isStatic() && member instanceof AllocatableMember)
                {
                    AllocatableMember allocatable = (AllocatableMember) member;
                    if(allocatable.parentNested == null)
                    {
                        int offsetAfter = allocatable.computeStructOffset(structSize);
                        if(structSize < offsetAfter) structSize = offsetAfter;
                    }
                }
            }
            fldStructMarked = true;
            fldStructSize = structSize;
        }
    }

    public final boolean hasNativeCallables() { return fldNativeCallablesCounter > 0; }

    public final boolean isSuperclass(ClassType type) {
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        if(type.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        for(ClassType current = fldSuperclassType; current != null; current = current.fldSuperclassType) if(type == current)
        {
            return true;
        }
        return false;
    }

    public final boolean isSuperclass(String specialCanonicalName) {
        if(specialCanonicalName != null && !specialCanonicalName.isEmpty())
        {
            for(ClassType current = fldSuperclassType; current != null; current = current.fldSuperclassType) if(specialCanonicalName.equals(current.specialCanonicalName)) return true;
        }
        return false;
    }

    public final boolean isSuperservice(ClassType type) {
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        if(type.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        return Array.indexOf(type, fldSuperservicesTypes, 0, fldSuperservicesLength) >= 0;
    }

    public final boolean isSuperservice(String specialCanonicalName) {
        if(specialCanonicalName != null && !specialCanonicalName.isEmpty())
        {
            for(ClassType[] types = fldSuperservicesTypes, int index = fldSuperservicesLength; index-- > 0; ) if(specialCanonicalName.equals(types[index].specialCanonicalName)) return true;
        }
        return false;
    }

    public final int getHelperForPosition() { return fldHelperForPosition; }

    public final int getSuperclassPosition() { return fldSuperclassPosition; }

    public final int getSuperservicesLength() { return fldSuperservicesLength; }

    public final int getSuperservicePositionAt(int index) {
        if(fldSuperservicesLength <= 0)
        {
            throw new ArrayIndexOutOfBoundsException(avt.lang.package.getResourceString("out-of-bounds.array-index"));
        }
        return fldSuperservicesPositions[index];
    }

    public final int getSuperserviceIndex(ClassType type) {
        if(type == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "type" }));
        }
        if(type.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("type.not-same-programme.type"));
        }
        return Array.indexOf(type, fldSuperservicesTypes, 0, fldSuperservicesLength);
    }

    public final Callable[] virtualCallables() {
        Callable[] result = fldVirtualCallables;
        if(result == null) return null;
        int length = result.length;
        Array.copy(result, 0, result = new Callable[length], 0, length);
        return result;
    }

    public final Callable[] serviceCallables() {
        Callable[] result = fldServiceCallables;
        if(result == null) return null;
        int length = result.length;
        Array.copy(result, 0, result = new Callable[length], 0, length);
        return result;
    }

    public final Fieldoid[] findFieldoids(String specialSimpleName, ClassType areVisibleFrom) {
        if(specialSimpleName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "specialSimpleName" }));
        }
        specialSimpleName = specialSimpleName.intern();
        ClassType place = fldHelperForType;
        if(place == null)
        {
            place = this;
        }
        if(areVisibleFrom == null)
        {
            areVisibleFrom = place;
        }
        else if(areVisibleFrom.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("visibility-type.not-same-programme"));
        }
        /* поиск полеоида в этом типе и его суперклассах, с учётом видимости */
        {
            Fieldoid found0 = null;
            Fieldoid found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        Member member = container.getChildMember(specialSimpleName);
                        if(member instanceof Fieldoid && member.isVisibleFrom(areVisibleFrom, this))
                        {
                            if(found0 != null)
                            {
                                if(!container.isHelper() && !found0.parentType.isHelper())
                                {
                                    return new Fieldoid[] { found0 };
                                }
                                found1 = (Fieldoid) member;
                                break label0;
                            }
                            found0 = (Fieldoid) member;
                        }
                    }
                }
            } while((current = current.fldSuperclassType) != null);
            if(found0 != null)
            {
                return found1 == null ? new Fieldoid[] { found0 } : new Fieldoid[] { found0, found1 };
            }
        }
        /* поиск полеоидов в суперсервисах, с учётом видимости */
        {
            Fieldoid found0 = null;
            Fieldoid found1 = null;
            label0: for(ClassType[] types = place.fldSuperservicesTypes, int tlength = place.fldSuperservicesLength, int tindex = 0; tindex < tlength; tindex++)
            {
                ClassType current = types[tindex];
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        Member member = container.getChildMember(specialSimpleName);
                        if(member instanceof Fieldoid && member.isVisibleFrom(areVisibleFrom, this))
                        {
                            if(found0 != null)
                            {
                                found1 = (Fieldoid) member;
                                break label0;
                            }
                            found0 = (Fieldoid) member;
                        }
                    }
                }
            }
            if(found0 != null)
            {
                return found1 == null ? new Fieldoid[] { found0 } : new Fieldoid[] { found0, found1 };
            }
        }
        /* поиск полеоида в этом типе и его супертипах, без учёта видимости */
        {
            int tindex = -1;
            int tlength = place.fldSuperservicesLength;
            ClassType[] types = place.fldSuperservicesTypes;
            ClassType current = place;
            do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        Member member = container.getChildMember(specialSimpleName);
                        if(member instanceof Fieldoid)
                        {
                            return new Fieldoid[] { (Fieldoid) member };
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
        }
        return null;
    }

    public final Callable[] findInterrupts(String specialSimpleName, ClassType areVisibleFrom) {
        if(specialSimpleName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "specialSimpleName" }));
        }
        specialSimpleName = specialSimpleName.intern();
        ClassType place = fldHelperForType;
        if(place == null)
        {
            place = this;
        }
        if(areVisibleFrom == null)
        {
            areVisibleFrom = place;
        }
        else if(areVisibleFrom.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("visibility-type.not-same-programme"));
        }
        Callable callable;
        /* поиск прерывания в этом типе и его суперклассах, с учётом видимости */
        {
            Callable found0 = null;
            Callable found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        Member member = container.getChildMember(specialSimpleName);
                        if(member instanceof Callable && (callable = (Callable) member).isInterrupt() && member.isVisibleFrom(areVisibleFrom, this))
                        {
                            if(found0 != null)
                            {
                                if(!container.isHelper() && !found0.parentType.isHelper())
                                {
                                    return new Callable[] { found0 };
                                }
                                found1 = callable;
                                break label0;
                            }
                            found0 = callable;
                        }
                    }
                }
            } while((current = current.fldSuperclassType) != null);
            if(found0 != null)
            {
                return found1 == null ? new Callable[] { found0 } : new Callable[] { found0, found1 };
            }
        }
        /* поиск прерываний в суперсервисах, с учётом видимости */
        {
            Callable found0 = null;
            Callable found1 = null;
            label0: for(ClassType[] types = place.fldSuperservicesTypes, int tlength = place.fldSuperservicesLength, int tindex = 0; tindex < tlength; tindex++)
            {
                ClassType current = types[tindex];
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        Member member = container.getChildMember(specialSimpleName);
                        if(member instanceof Callable && (callable = (Callable) member).isInterrupt() && member.isVisibleFrom(areVisibleFrom, this))
                        {
                            if(found0 != null)
                            {
                                found1 = callable;
                                break label0;
                            }
                            found0 = callable;
                        }
                    }
                }
            }
            if(found0 != null)
            {
                return found1 == null ? new Callable[] { found0 } : new Callable[] { found0, found1 };
            }
        }
        /* поиск прерывания в этом типе и его супертипах, без учёта видимости */
        {
            int tindex = -1;
            int tlength = place.fldSuperservicesLength;
            ClassType[] types = place.fldSuperservicesTypes;
            ClassType current = place;
            do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        Member member = container.getChildMember(specialSimpleName);
                        if(member instanceof Callable && (callable = (Callable) member).isInterrupt())
                        {
                            return new Callable[] { callable };
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
        }
        return null;
    }

    public final InstInit[] findConstructors(Type[] arguments, ClassType areVisibleFrom) {
        if(areVisibleFrom == null)
        {
            areVisibleFrom = this;
        }
        else if(areVisibleFrom.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("visibility-type.not-same-programme"));
        }
        if(isHelper())
        {
            return null;
        }
        InstInit constructor;
        /* определение места поиска конструкторов */
        ClassType current = this;
        while(!current.isClass()) if((current = current.fldSuperclassType) == null)
        {
            return null;
        }
        /* первый конструктор */
        ProgrammeItem first = current.getChildMember(SPECNAME_INST_INIT);
        /* поиск конструктора с точно совпадающими типами аргументов и с учётом видимости */
        for(ProgrammeItem member = first; member != null; member = member.nextItem)
        {
            if(member instanceof InstInit && (constructor = (InstInit) member).isVisibleFrom(areVisibleFrom, this) && constructor.isIdentityArguments(arguments))
            {
                return new InstInit[] { constructor };
            }
        }
        /* поиск конструкторов с конвертируемыми типами аргументов и с учётом видимости */
        {
            InstInit found0 = null;
            InstInit found1 = null;
            for(ProgrammeItem member = first; member != null; member = member.nextItem)
            {
                if(member instanceof InstInit && (constructor = (InstInit) member).isVisibleFrom(areVisibleFrom, this) && constructor.isConvertableArguments(arguments))
                {
                    if(found0 != null)
                    {
                        found1 = constructor;
                        break;
                    }
                    found0 = constructor;
                }
            }
            if(found0 != null)
            {
                return found1 == null ? new InstInit[] { found0 } : new InstInit[] { found0, found1 };
            }
        }
        /* поиск конструктора с точно совпадающими типами аргументов и без учёта видимости */
        for(ProgrammeItem member = first; member != null; member = member.nextItem)
        {
            if(member instanceof InstInit && (constructor = (InstInit) member).isIdentityArguments(arguments))
            {
                return new InstInit[] { constructor };
            }
        }
        /* поиск конструкторов с конвертируемыми типами аргументов и без учёта видимости */
        {
            InstInit found0 = null;
            InstInit found1 = null;
            for(ProgrammeItem member = first; member != null; member = member.nextItem)
            {
                if(member instanceof InstInit && (constructor = (InstInit) member).isConvertableArguments(arguments))
                {
                    if(found0 != null)
                    {
                        found1 = constructor;
                        break;
                    }
                    found0 = constructor;
                }
            }
            if(found0 != null)
            {
                return found1 == null ? new InstInit[] { found0 } : new InstInit[] { found0, found1 };
            }
        }
        /* поиск конструктора с любыми типами аргументов и без учёта видимости */
        return !(first instanceof InstInit) ? null : new InstInit[] { (InstInit) first };
    }

    public final Method[] findMethods(String specialSimpleName, Type[] arguments, ClassType areVisibleFrom) {
        if(specialSimpleName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "specialSimpleName" }));
        }
        specialSimpleName = specialSimpleName.intern();
        ClassType place = fldHelperForType;
        if(place == null)
        {
            place = this;
        }
        if(areVisibleFrom == null)
        {
            areVisibleFrom = place;
        }
        else if(areVisibleFrom.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("visibility-type.not-same-programme"));
        }
        int tlength = place.fldSuperservicesLength;
        ClassType[] types = place.fldSuperservicesTypes;
        Method callable;
        /* поиск метода в этом типе и его супертипах, с точно совпадающими типами аргументов и с учётом видимости */
        {
            int tindex = -1;
            Method found0 = null;
            Method found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Method && (callable = (Method) member).isVisibleFrom(areVisibleFrom, this) && callable.isIdentityArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Method[] { found0 } : new Method[] { found0, found1 };
            }
        }
        /* поиск методов в этом типе и его супертипах, с конвертируемыми типами аргументов и с учётом видимости */
        {
            int tindex = -1;
            Method found0 = null;
            Method found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Method && (callable = (Method) member).isVisibleFrom(areVisibleFrom, this) && callable.isConvertableArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Method[] { found0 } : new Method[] { found0, found1 };
            }
        }
        /* поиск метода в этом типе и его супертипах, с точно совпадающими типами аргументов и без учёта видимости */
        {
            int tindex = -1;
            Method found0 = null;
            Method found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Method && (callable = (Method) member).isIdentityArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Method[] { found0 } : new Method[] { found0, found1 };
            }
        }
        /* поиск методов в этом типе и его супертипах, с конвертируемыми типами аргументов и без учёта видимости */
        {
            int tindex = -1;
            Method found0 = null;
            Method found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Method && (callable = (Method) member).isConvertableArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Method[] { found0 } : new Method[] { found0, found1 };
            }
        }
        /* поиск методов в этом типе и его супертипах, с любыми типами аргументов и без учёта видимости */
        {
            int tindex = -1;
            ClassType current = place;
            do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem) if(member instanceof Method)
                        {
                            return new Method[] { (Method) member };
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
        }
        return null;
    }

    public final Operator[] findOperators(int kind, Type[] arguments, ClassType areVisibleFrom) {
        String specialSimpleName = Operator.kindToSpecialSimpleName(kind);
        ClassType place = fldHelperForType;
        if(place == null)
        {
            place = this;
        }
        if(areVisibleFrom == null)
        {
            areVisibleFrom = place;
        }
        else if(areVisibleFrom.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("visibility-type.not-same-programme"));
        }
        int tlength = place.fldSuperservicesLength;
        ClassType[] types = place.fldSuperservicesTypes;
        Operator callable;
        /* поиск оператора в этом типе и его супертипах, с точно совпадающими типами аргументов и с учётом видимости */
        {
            int tindex = -1;
            Operator found0 = null;
            Operator found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Operator && (callable = (Operator) member).isVisibleFrom(areVisibleFrom, this) && callable.isIdentityArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Operator[] { found0 } : new Operator[] { found0, found1 };
            }
        }
        /* поиск операторов в этом типе и его супертипах, с конвертируемыми типами аргументов и с учётом видимости */
        {
            int tindex = -1;
            Operator found0 = null;
            Operator found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Operator && (callable = (Operator) member).isVisibleFrom(areVisibleFrom, this) && callable.isConvertableArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Operator[] { found0 } : new Operator[] { found0, found1 };
            }
        }
        /* поиск оператора в этом типе и его супертипах, с точно совпадающими типами аргументов и без учёта видимости */
        {
            int tindex = -1;
            Operator found0 = null;
            Operator found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Operator && (callable = (Operator) member).isIdentityArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Operator[] { found0 } : new Operator[] { found0, found1 };
            }
        }
        /* поиск операторов в этом типе и его супертипах, с конвертируемыми типами аргументов и без учёта видимости */
        {
            int tindex = -1;
            Operator found0 = null;
            Operator found1 = null;
            ClassType current = place;
            label0: do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem)
                        {
                            if(member instanceof Operator && (callable = (Operator) member).isConvertableArguments(arguments))
                            {
                                if(found0 == null)
                                {
                                    found0 = callable;
                                    continue;
                                }
                                if(!found0.isIdentityArguments(callable) || container.isHelper() || found0.parentType.isHelper())
                                {
                                    found1 = callable;
                                    break label0;
                                }
                            }
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
            if(found0 != null)
            {
                return found1 == null ? new Operator[] { found0 } : new Operator[] { found0, found1 };
            }
        }
        /* поиск операторов в этом типе и его супертипах, с любыми типами аргументов и без учёта видимости */
        {
            int tindex = -1;
            ClassType current = place;
            do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || areVisibleFrom.source.contains(container) && container.isVisibleFrom(areVisibleFrom))
                    {
                        for(ProgrammeItem member = container.getChildMember(specialSimpleName); member != null; member = member.nextItem) if(member instanceof Operator)
                        {
                            return new Operator[] { (Operator) member };
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
        }
        return null;
    }

    public final Member resolveName(String specialSimpleName, ClassType isVisibleFrom, boolean isVisibleOnly) {
        if(specialSimpleName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "specialSimpleName" }));
        }
        ClassType place = fldHelperForType;
        if(place == null)
        {
            place = this;
        }
        if(isVisibleFrom == null)
        {
            isVisibleFrom = place;
        }
        else if(isVisibleFrom.parentProgramme != parentProgramme)
        {
            throw new IllegalArgumentException(package.getResourceString("visibility-type.not-same-programme"));
        }
        int tlength = place.fldSuperservicesLength;
        ClassType[] types = place.fldSuperservicesTypes;
        /* поиск члена в этом типе и его супертипах, с учётом видимости */
        {
            int tindex = -1;
            ClassType current = place;
            do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || isVisibleFrom.source.contains(container) && container.isVisibleFrom(isVisibleFrom))
                    {
                        for(Member member = container.getChildMember(specialSimpleName); member != null; member = (Member) member.nextItem)
                        {
                            if(member.isVisibleFrom(isVisibleFrom, this)) return member;
                        }
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
        }
        /* поиск члена в этом типе и его супертипах, без учёта видимости */
        if(!isVisibleOnly)
        {
            int tindex = -1;
            ClassType current = place;
            do
            {
                for(ClassType[] helpers = current.fldHelpers.array, int hlength = helpers.length, int hindex = -1; hindex < hlength; hindex++)
                {
                    ClassType container = hindex < 0 ? current : helpers[hindex];
                    if(current == container || isVisibleFrom.source.contains(container) && container.isVisibleFrom(isVisibleFrom))
                    {
                        Member member = container.getChildMember(specialSimpleName);
                        if(member != null) return member;
                    }
                }
                if(tindex < 0 && (current = current.fldSuperclassType) == null)
                {
                    tindex = 0;
                }
                if(tindex >= 0)
                {
                    current = tindex >= tlength ? null : types[tindex];
                    tindex++;
                }
            } while(current != null);
        }
        return null;
    }

    public final Member getChildMember(String specialSimpleName) { return (Member) super.getChildItem(specialSimpleName); }

    public final Member getChildMember(String specialSimpleName, boolean ignoreCase) { return (Member) super.getChildItem(specialSimpleName, ignoreCase); }

    public final Callable getChildCallable(String specialSimpleName, Type[] arguments) {
        for(ProgrammeItem member = super.getChildItem(specialSimpleName); member != null; member = member.nextItem) if(member instanceof Callable)
        {
            Callable callable = (Callable) member;
            if(callable.isIdentityArguments(arguments)) return callable;
        }
        return null;
    }

    public final Callable getChildCallable(String specialSimpleName, TypedItem[] arguments) {
        for(ProgrammeItem member = super.getChildItem(specialSimpleName); member != null; member = member.nextItem) if(member instanceof Callable)
        {
            Callable callable = (Callable) member;
            if(callable.isIdentityArguments(arguments)) return callable;
        }
        return null;
    }

    public final Fieldoid getChildFieldoid(String specialSimpleName) {
        for(ProgrammeItem member = super.getChildItem(specialSimpleName); member != null; member = member.nextItem) if(member instanceof Fieldoid)
        {
            return (Fieldoid) member;
        }
        return null;
    }

    public final InstInit getDefaultConstructor() { return fldDefaultConstructor; }

    public final ClassInit getStaticBlock() { return fldStaticBlock; }

    public final ClassType getHelperForType() { return fldHelperForType; }

    public final ClassType getSuperclassType() { return fldSuperclassType; }

    public final ClassType getSuperserviceTypeAt(int index) {
        if(index < 0 || index >= fldSuperservicesLength)
        {
            throw new ArrayIndexOutOfBoundsException(avt.lang.package.getResourceString("out-of-bounds.array-index"));
        }
        return fldSuperservicesTypes[index];
    }

    public final int structSize { read = fldStructSize }

    public final int instanceSize { read = fldInstanceSize }

    public final String outputPath { read = fldOutputPath }

    public final Member operator [](int index) { return (Member) super.operator [](index); }

    protected void insertChildItem(ProgrammeItem item, int position) {
        if(item != null && !(item instanceof Member))
        {
            throw new IllegalArgumentException(package.getResourceString("adding-item.not-a-member"));
        }
        super.insertChildItem(item, position);
        if(item instanceof Callable && ((Callable) item).isNative())
        {
            fldNativeCallablesCounter++;
        }
        if(item instanceof ClassInit)
        {
            fldStaticBlock = (ClassInit) item;
        }
        else if(item instanceof InstInit)
        {
            InstInit constructor = (InstInit) item;
            if(constructor.arguments.length <= 0) fldDefaultConstructor = constructor;
        }
    }

    protected void removeChildItem(ProgrammeItem item) {
        if(item instanceof Callable && ((Callable) item).isNative())
        {
            fldNativeCallablesCounter--;
        }
        if(fldStaticBlock == item)
        {
            fldStaticBlock = null;
        }
        else if(fldDefaultConstructor == item)
        {
            fldDefaultConstructor = null;
        }
        super.removeChildItem(item);
    }

    protected ReferenceType getCommonType(ReferenceType anot) { return isAssignableFrom(anot) ? this : anot.isAssignableFrom(this) ? anot : null; }

    protected String composeRecompilableName() { return "L" + specialCanonicalName; }

    protected String composeFasmSimpleName() { return specialCanonicalName; }

    protected String composeFasmFullName() { return specialCanonicalName; }

    protected String composeFasmFileName() { return specialSimpleName; }

    package final void initSubtypes() {
        Programme programme = parentProgramme;
        ClassType superclass = fldSuperclassType;
        int count = programme.classes.length + programme.arrays.length;
        int index = 0;
        if(superclass != null) do
        {
            if(index++ >= count)
            {
                throw new IllegalClassTypeStateException(package.getResourceString("class-type.!error.init-subtypes"));
            }
            ClassTypeArray stypes = superclass.fldSubtypes;
            if(stypes != null) stypes.append(this);
        } while((superclass = superclass.fldSuperclassType) != null);
    }

    package final Local thisArgument { read = fldThisArgument }

    private ClassType[] getSubtypesStore() {
        ClassTypeArray stypes = fldSubtypes;
        return stypes == null ? null : stypes.array;
    }

    private Local createThisArgument() {
        Programme programme = parentProgramme;
        Local result = programme == null ? null : programme.newLocal(true, this, SPECNAME_THIS, null, null, -1);
        if(result == null) result = new Local(true, this, SPECNAME_THIS, null, null, -1);
        return result;
    }
}