PrimitiveType.avt

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

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

    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);
    }
}