Member.avt

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

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

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

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

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

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

package ru.malik.elaborarer.avtoo.lang;

import avt.lang.array.*;

public abstract class Member(ReflectItem, Cloneable, Measureable, ObjectArray, AVTOOConstants)
{
    private static boolean isClassTypeAssignable(ClassType type, ClassType anot) { return anot == type || anot.isSuperclass(type) || anot.isSuperservice(type); }

    private final ClassType fldParentType;
    private final Package fldParentPackage;

    package (ClassType parentType, int attributes, String specialSimpleName, int declarationPosition, int documentationPosition):
        super(parentType, attributes, specialSimpleName, parentType == null ? null : parentType.source, declarationPosition, documentationPosition) {
        fldParentType = parentType;
        fldParentPackage = parentType == null ? null : parentType.parentPackage;
    }

    public boolean isVisibleFrom(ClassType type) { return isVisibleFrom(type, null); }

    public boolean isVisibleFrom(ClassType type, ClassType impliedParentType) {
        ClassType factEnclosingType = fldParentType;
        if(factEnclosingType == null)
        {
            throw new IllegalMemberStateException(package.getResourceString("no-parent-item.member"));
        }
        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.member"));
        }
        ClassType realEnclosingType = factEnclosingType.getRealType();
        impliedParentType = impliedParentType == null ? realEnclosingType : impliedParentType.getRealType();
        if(impliedParentType.parentProgramme != programme)
        {
            throw new IllegalArgumentException(package.getResourceString("implied-parent-type.not-same-programme"));
        }
        if(!isClassTypeAssignable(realEnclosingType, impliedParentType))
        {
            throw new IllegalArgumentException(package.getResourceString("implied-parent-type.not-assignable"));
        }
        switch(visibility)
        {
        default:
            /* Недостижимый код. Нужен только для того, чтобы избежать сообщений об ошибках от компилятора. */
            throw new IllegalMemberStateException(/*этот член имеет неизвестную видимость*/);
        case PUBLIC:
        case PUBLISHED:
            return true;
        case PROTECTED:
            if(type.parentPackage == factEnclosingType.parentPackage)
            {
                return true;
            }
            return !type.isHelper() && factEnclosingType == realEnclosingType && isClassTypeAssignable(realEnclosingType, type) && isClassTypeAssignable(type, impliedParentType);
        case PACKAGE:
        case RESERVED_PACKAGE:
            Object pck = type.parentPackage;
            if(pck != null && pck == impliedParentType.parentPackage)
            {
                int index = -1;
                int length = impliedParentType.getSuperservicesLength();
                ClassType current = impliedParentType.getSuperclassType();
                if(current == null && length > 0)
                {
                    current = impliedParentType.getSuperserviceTypeAt(0);
                    index = 1;
                }
                while(current != null)
                {
                    if(isClassTypeAssignable(realEnclosingType, current) && isClassTypeAssignable(current, impliedParentType) && pck != current.parentPackage)
                    {
                        return false;
                    }
                    if(index < 0 && (current = current.getSuperclassType()) == null)
                    {
                        index = 0;
                    }
                    if(index >= 0)
                    {
                        current = index >= length ? null : impliedParentType.getSuperserviceTypeAt(index);
                        index++;
                    }
                }
                return true;
            }
            return false;
        case SOURCE:
        case RESERVED_SOURCE:
            Source src = type.source;
            Object pck = type.parentPackage;
            if(pck != null && pck == impliedParentType.parentPackage && src != null && src.isSameSource(impliedParentType.source))
            {
                int index = -1;
                int length = impliedParentType.getSuperservicesLength();
                ClassType current = impliedParentType.getSuperclassType();
                if(current == null && length > 0)
                {
                    current = impliedParentType.getSuperserviceTypeAt(0);
                    index = 1;
                }
                while(current != null)
                {
                    if(isClassTypeAssignable(realEnclosingType, current) && isClassTypeAssignable(current, impliedParentType) && (pck != current.parentPackage || !src.isSameSource(current.source)))
                    {
                        return false;
                    }
                    if(index < 0 && (current = current.getSuperclassType()) == null)
                    {
                        index = 0;
                    }
                    if(index >= 0)
                    {
                        current = index >= length ? null : impliedParentType.getSuperserviceTypeAt(index);
                        index++;
                    }
                }
                return true;
            }
            return false;
        case PRIVATE:
            return type == factEnclosingType && realEnclosingType == impliedParentType;
        }
    }

    public boolean isSpecial() { return false; }

    public final boolean isStatic() { return (attributes & ATTR_STATIC) != 0; }

    public final boolean isSynthetic() { return (attributes & ATTR_SYNTHETIC) != 0; }

    public final ClassType parentType { read = fldParentType }

    public final Package parentPackage { read = fldParentPackage }

    protected abstract String composeRecompilableName();

    protected abstract String composeFasmSimpleName();

    protected abstract String composeFasmFullName();
}