/*
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package ru.malik.elaborarer.avtoo.lang;
import avt.lang.array.*;
public class ArrayType(ClassType, Cloneable, Measureable, ObjectArray, AllocatableFactory, AVTOOConstants)
{
private static Type check(Type componentType) {
if(componentType == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "componentType" }));
}
return componentType;
}
private boolean fldCompilable;
private final int fldDimensionsCount;
private final Type fldComponentType;
private final Type fldCellType;
public (Type componentType):
super(check(componentType).parentPackage, componentType.visibility, componentType.specialSimpleName + "[]", null, -1, -1, null) {
if(!(componentType instanceof ArrayType))
{
fldDimensionsCount = 1;
fldCellType = componentType;
} else
{
ArrayType array = (ArrayType) componentType;
fldDimensionsCount = array.fldDimensionsCount + 1;
fldCellType = array.fldCellType;
}
fldComponentType = componentType;
}
public void makeCompilable() {
if(!fldCompilable)
{
fldCompilable = true;
for(Type componentType = fldComponentType; componentType instanceof ArrayType; )
{
ArrayType array = (ArrayType) componentType;
array.fldCompilable = true;
componentType = array.fldComponentType;
}
}
}
public boolean isCompilable() { return fldCompilable; }
public boolean isAssignableFrom(Type anot) {
if(anot == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "anot" }));
}
if(anot == this || anot.isNull()) return true;
if(!(anot instanceof ArrayType)) return false;
ArrayType array = (ArrayType) anot;
int thisDimensionsCount = fldDimensionsCount;
int anotDimensionsCount = array.fldDimensionsCount;
if(thisDimensionsCount > anotDimensionsCount) return false;
Type cell = array.fldComponentType;
for(int dimCount = thisDimensionsCount; dimCount-- > 1; ) cell = ((ArrayType) cell).fldComponentType;
return fldCellType.isAssignableFrom(cell);
}
public boolean isCompatibleWith(Type anot) {
if(!(anot instanceof ArrayType)) return super.isCompatibleWith(anot);
ArrayType array = (ArrayType) anot;
int thisDimensionsCount = fldDimensionsCount;
int anotDimensionsCount = array.fldDimensionsCount;
Type typeA;
Type typeB;
if(thisDimensionsCount > anotDimensionsCount)
{
typeA = array.fldCellType;
typeB = fldComponentType;
for(int dimCount = anotDimensionsCount; dimCount-- > 1; ) typeB = ((ArrayType) typeB).fldComponentType;
} else
{
typeA = fldCellType;
typeB = array.fldComponentType;
for(int dimCount = thisDimensionsCount; dimCount-- > 1; ) typeB = ((ArrayType) typeB).fldComponentType;
}
return typeA.isCompatibleWith(typeB);
}
public boolean isArray() { return true; }
public final int dimensionsCount { read = fldDimensionsCount }
public final Type componentType { read = fldComponentType }
public final Type cellType { read = fldCellType }
protected String composeRecompilableName() { return "[" + fldComponentType.recompilableName; }
protected String composeFasmSimpleName() { return fldCellType.fasmSimpleName + composeFasmDimensionsCount(); }
protected String composeFasmFullName() { return fasmSimpleName; }
protected String composeFasmFileName() { return fldCellType.fasmFileName + composeFasmDimensionsCount(); }
private String composeFasmDimensionsCount() {
int dimensions = fldDimensionsCount;
return new String(new char[] { '.', (char) ('0' + dimensions / 10), (char) ('0' + dimensions % 10), 'd' });
}
}