/*
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package ru.malik.elaborarer.avtoo.lang;
import avt.lang.array.*;
public final class PrimitiveType(Type, Cloneable, Measureable, ObjectArray, AVTOOConstants)
{
public static int recompilableNameToKind(String name) {
if(name == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "name" }));
}
if(name.equals("V")) return VOID;
if(name.equals("Z")) return BOOLEAN;
if(name.equals("C")) return CHAR;
if(name.equals("R")) return REAL;
if(name.equals("D")) return DOUBLE;
if(name.equals("D2")) return DOUBLE2;
if(name.equals("D4")) return DOUBLE4;
if(name.equals("D8")) return DOUBLE8;
if(name.equals("F")) return FLOAT;
if(name.equals("F2")) return FLOAT2;
if(name.equals("F4")) return FLOAT4;
if(name.equals("F8")) return FLOAT8;
if(name.equals("B")) return BYTE;
if(name.equals("B2")) return BYTE2;
if(name.equals("B4")) return BYTE4;
if(name.equals("B8")) return BYTE8;
if(name.equals("S")) return SHORT;
if(name.equals("S2")) return SHORT2;
if(name.equals("S4")) return SHORT4;
if(name.equals("S8")) return SHORT8;
if(name.equals("I")) return INT;
if(name.equals("I2")) return INT2;
if(name.equals("I4")) return INT4;
if(name.equals("I8")) return INT8;
if(name.equals("J")) return LONG;
if(name.equals("J2")) return LONG2;
if(name.equals("J4")) return LONG4;
if(name.equals("J8")) return LONG8;
throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "name" }));
}
public static String kindToRecompilableName(int kind) {
switch(kind)
{
case VOID:
return "V";
case BOOLEAN:
return "Z";
case CHAR:
return "C";
case REAL:
return "R";
case DOUBLE:
return "D";
case DOUBLE2:
return "D2";
case DOUBLE4:
return "D4";
case DOUBLE8:
return "D8";
case FLOAT:
return "F";
case FLOAT2:
return "F2";
case FLOAT4:
return "F4";
case FLOAT8:
return "F8";
case BYTE:
return "B";
case BYTE2:
return "B2";
case BYTE4:
return "B4";
case BYTE8:
return "B8";
case SHORT:
return "S";
case SHORT2:
return "S2";
case SHORT4:
return "S4";
case SHORT8:
return "S8";
case INT:
return "I";
case INT2:
return "I2";
case INT4:
return "I4";
case INT8:
return "I8";
case LONG:
return "J";
case LONG2:
return "J2";
case LONG4:
return "J4";
case LONG8:
return "J8";
default:
throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "kind" }));
}
}
public static String kindToSpecialSimpleName(int kind) {
switch(kind)
{
case VOID:
return "void";
case BOOLEAN:
return "boolean";
case CHAR:
return "char";
case REAL:
return "real";
case DOUBLE:
return "double";
case DOUBLE2:
return "double2";
case DOUBLE4:
return "double4";
case DOUBLE8:
return "double8";
case FLOAT:
return "float";
case FLOAT2:
return "float2";
case FLOAT4:
return "float4";
case FLOAT8:
return "float8";
case BYTE:
return "byte";
case BYTE2:
return "byte2";
case BYTE4:
return "byte4";
case BYTE8:
return "byte8";
case SHORT:
return "short";
case SHORT2:
return "short2";
case SHORT4:
return "short4";
case SHORT8:
return "short8";
case INT:
return "int";
case INT2:
return "int2";
case INT4:
return "int4";
case INT8:
return "int8";
case LONG:
return "long";
case LONG2:
return "long2";
case LONG4:
return "long4";
case LONG8:
return "long8";
default:
throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "kind" }));
}
}
private final int fldKind;
private final int fldVectorLength;
private final int fldVectorBaseKind;
private final PrimitiveType fldVectorBaseType;
public (Package parentPackage, int kind):
super(parentPackage, PUBLIC | ATTR_FINAL | ATTR_PRIMITIVE, kindToSpecialSimpleName(kind), null, -1, -1) {
int baseKind = kind < REAL || kind >= VOID + PRIMITIVES_LENGTH ? kind : kind & ~0x03;
Programme programme = parentProgramme;
fldKind = kind;
fldVectorLength = kind == VOID ? 0 : kind < REAL || kind >= VOID + PRIMITIVES_LENGTH ? 1 : 1 << (kind & 0x03);
fldVectorBaseKind = baseKind;
fldVectorBaseType = kind == baseKind ? this : programme == null ? null : programme.getPrimitiveType(baseKind);
}
public boolean isAssignableFrom(Type anot) { return isSameType(anot); }
public boolean isConvertableFrom(Type anot) {
if(anot == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "anot" }));
}
if(!(anot instanceof PrimitiveType))
{
return false;
}
PrimitiveType prim = (PrimitiveType) anot;
int tvl = fldVectorLength;
int tvb = fldVectorBaseKind;
int avl = prim.fldVectorLength;
int avb = prim.fldVectorBaseKind;
switch(tvb)
{
case BOOLEAN:
case CHAR:
return avb == tvb;
case BYTE:
case SHORT:
return avb >= BYTE && avb <= tvb && avl <= tvl;
case INT:
case LONG:
return avb == CHAR || avb >= BYTE && avb <= tvb && avl <= tvl;
case FLOAT:
return avb == CHAR || avb >= FLOAT && avb <= SHORT && avl <= tvl;
case DOUBLE:
return avb == CHAR || avb >= DOUBLE && avb <= INT && avl <= tvl;
case REAL:
return avb == CHAR || avb >= REAL && avb <= LONG && avl == 1;
default:
return false;
}
}
public boolean isCompatibleWith(Type anot) { return isSameType(anot); }
public boolean isPrimitive() { return true; }
public boolean isVoid() { return fldKind == VOID; }
public boolean isBoolean() { return fldKind == BOOLEAN; }
public boolean isChar() { return fldKind == CHAR; }
public boolean isInt() {
int kind = fldKind;
return kind == CHAR || kind == BYTE || kind == SHORT || kind == INT;
}
public boolean isLong() {
int kind = fldKind;
return kind == CHAR || kind == BYTE || kind == SHORT || kind == INT || kind == LONG;
}
public boolean isVector() {
int kind = fldKind;
return kind >= REAL && kind < VOID + PRIMITIVES_LENGTH && (kind & 0x03) > 0;
}
public boolean isNumeric() {
int kind = fldKind;
return kind == CHAR || kind >= REAL && kind < VOID + PRIMITIVES_LENGTH;
}
public boolean isFloating() {
int kind = fldKind;
return kind >= REAL && kind <= FLOAT8;
}
public boolean isStackable() {
int kind = fldKind;
return kind >= REAL && kind < VOID + PRIMITIVES_LENGTH && kind != BYTE && kind != SHORT;
}
public int toStackable() {
int kind = fldKind;
return kind >= REAL && kind < VOID + PRIMITIVES_LENGTH && kind != BYTE && kind != SHORT ? kind : kind == VOID ? 0 : INT;
}
public PrimitiveType getScalarCommonType(Type anot) { return getCommonType(anot, false); }
public PrimitiveType getVectorCommonType(Type anot) { return getCommonType(anot, true); }
public int kind { read = fldKind }
public int vectorLength { read = fldVectorLength }
public int vectorBaseKind { read = fldVectorBaseKind }
public PrimitiveType vectorBaseType { read = fldVectorBaseType }
protected int computeFieldWidth() {
switch(fldKind)
{
default:
return 0;
case BOOLEAN:
case BYTE:
return 1;
case CHAR:
case BYTE2:
case SHORT:
return 2;
case BYTE4:
case SHORT2:
case INT:
case FLOAT:
return 4;
case BYTE8:
case SHORT4:
case INT2:
case LONG:
case FLOAT2:
case DOUBLE:
return 8;
case REAL:
return 10;
case SHORT8:
case INT4:
case LONG2:
case FLOAT4:
case DOUBLE2:
return 16;
case INT8:
case LONG4:
case FLOAT8:
case DOUBLE4:
return 32;
case LONG8:
case DOUBLE8:
return 64;
}
}
protected String composeRecompilableName() { return kindToRecompilableName(fldKind); }
protected String composeFasmSimpleName() { return specialSimpleName; }
protected String composeFasmFullName() { return specialSimpleName + ".primitive"; }
protected String composeFasmFileName() { return specialSimpleName; }
private boolean isSameType(Type anot) {
if(anot == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "anot" }));
}
return anot == this || anot instanceof PrimitiveType && ((PrimitiveType) anot).fldKind == fldKind;
}
private PrimitiveType getCommonType(Type anot, boolean isVector) {
if(anot == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "anot" }));
}
if(!(anot instanceof PrimitiveType)) return null;
Programme programme = parentProgramme;
PrimitiveType prim = (PrimitiveType) anot;
int tkn = fldKind;
int akn = prim.fldKind;
int tvl = tkn & 0x03;
int tvb = fldVectorBaseKind;
int avl = akn & 0x03;
int avb = prim.fldVectorBaseKind;
switch(tvb)
{
case VOID:
return null;
case BOOLEAN:
return avb == BOOLEAN ? this : null;
case CHAR:
if(isVector)
{
if(avb == CHAR) return this;
if(avb == VOID || avb == BOOLEAN) return null;
}
tvl = 0;
tvb = INT;
}
switch(avb)
{
case VOID:
return null;
case BOOLEAN:
return tvb == BOOLEAN ? prim : null;
case CHAR:
if(isVector)
{
if(tvb == CHAR) return prim;
if(tvb == VOID || tvb == BOOLEAN) return null;
}
avl = 0;
avb = INT;
}
int cvb;
switch(tvb)
{
case BYTE:
cvb = avb;
break;
case SHORT:
cvb = avb == BYTE ? SHORT : avb;
break;
case INT:
cvb = avb >= BYTE && avb <= SHORT ? INT : avb == FLOAT ? DOUBLE : avb;
break;
case LONG:
cvb = avb >= REAL && avb <= FLOAT ? REAL : LONG;
break;
case FLOAT:
cvb = avb >= FLOAT && avb <= SHORT ? FLOAT : avb >= DOUBLE && avb <= INT ? DOUBLE : REAL;
break;
case DOUBLE:
cvb = avb == REAL || avb == LONG ? REAL : DOUBLE;
break;
case REAL:
cvb = REAL;
break;
default:
return null;
}
int ckn = (!isVector && cvb >= BYTE && cvb <= SHORT ? INT : cvb) + Int.max(tvl, avl);
return tkn == ckn ? this : akn == ckn ? prim : programme == null ? null : programme.getPrimitiveType(ckn);
}
}