/*
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
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();
}