AssemblerElementWriter.avt

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

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

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

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

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

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

package ru.malik.elaborarer.avtoo.generator;

import avt.lang.array.*;
import ru.malik.elaborarer.avtoo.lang.*;

public class AssemblerElementWriter(Object, AVTOOConstants)
{
    /*<fold флаги формирования сигнатуры типа>*/
    public static final int NORM  = 0;
    public static final int WEAK  = 1;
    public static final int STACK = 2;
    /*</fold>*/

    protected int fldOffset;
    protected char[] fldText;

    public () {  }

    public void trim() { fldText.length = fldOffset; }

    public char[] get() {
        char[] result = fldText;
        result.length = fldOffset;
        return result;
    }

    public AssemblerElementWriter set(char[] text, int offset) {
        fldText = text;
        fldOffset = offset;
        text.length = text.capacity;
        return this;
    }

    public AssemblerElementWriter writeChar(char character) {
        int offset = fldOffset;
        fldText[offset++] = character;
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeLabel(char character, int label) {
        int length = 7;
        if(label >= 0x00010000 && label < 0x01000000)
        {
            length = 9;
        }
        else if(label >= 0x01000000 || label < 0x00000000)
        {
            length = 11;
        }
        int offset = fldOffset;
        for(char[] text = fldText, text[offset] = text[offset + 2] = '.', text[offset + 1] = character, offset += 3, int index = 3; index < length; index++)
        {
            text[offset++] = Char.toUpperCase(Char.toChar((label >> (length - index - 1 << 2)) & 0x0f));
        }
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeLabel(int label) {
        int length = 7;
        if(label >= 0x00010000 && label < 0x01000000)
        {
            length = 9;
        }
        else if(label >= 0x01000000 || label < 0x00000000)
        {
            length = 11;
        }
        int offset = fldOffset;
        for(char[] text = fldText, text[offset++] = '.', text[offset++] = text[offset + length - 3] = '$', int index = 3; index < length; index++)
        {
            text[offset++] = Char.toChar((label >> (length - index - 1 << 2)) & 0x0f);
        }
        fldOffset = offset + 1;
        return this;
    }

    public AssemblerElementWriter writeOffset(int value) {
        int length = 2;
        if(value >= 0x00000010 && value < 0x00000100)
        {
            length = 3;
        }
        else if(value >= 0x00000100 && value < 0x00001000)
        {
            length = 4;
        }
        else if(value >= 0x00001000 && value < 0x00010000)
        {
            length = 5;
        }
        else if(value >= 0x00010000 && value < 0x00100000)
        {
            length = 6;
        }
        else if(value >= 0x00100000 && value < 0x01000000)
        {
            length = 7;
        }
        else if(value >= 0x01000000 && value < 0x10000000)
        {
            length = 8;
        }
        else if(value >= 0x10000010 || value < 0x00000000)
        {
            length = 9;
        }
        int offset = fldOffset;
        for(char[] text = fldText, text[offset++] = '$', int index = 1; index < length; index++)
        {
            text[offset++] = Char.toChar((int) (value >> (length - index - 1 << 2)) & 0x0f);
        }
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeByte(int value) {
        int offset = fldOffset;
        for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 3; index++)
        {
            text[offset++] = Char.toChar((int) (value >> (2 - index << 2)) & 0x0f);
        }
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeShort(int value) {
        int offset = fldOffset;
        for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 5; index++)
        {
            text[offset++] = Char.toChar((int) (value >> (4 - index << 2)) & 0x0f);
        }
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeInt(int value) {
        int offset = fldOffset;
        for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 9; index++)
        {
            text[offset++] = Char.toChar((int) (value >> (8 - index << 2)) & 0x0f);
        }
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeLong(long value) {
        int offset = fldOffset;
        for(char[] text = fldText, text[offset++] = '$', int index = 1; index < 17; index++)
        {
            text[offset++] = Char.toChar((int) (value >> (16 - index << 2)) & 0x0f);
        }
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeDecimal(int value) {
        int offset = fldOffset;
        char[] text = fldText;
        if(value >= 0)
        {
            value = -value;
        } else
        {
            text[offset++] = '-';
        }
        int length = -1;
        if(value > -100 && value <= -10)
        {
            length = -2;
        }
        else if(value > -1000 && value <= -100)
        {
            length = -3;
        }
        else if(value > -10000 && value <= -1000)
        {
            length = -4;
        }
        else if(value > -100000 && value <= -10000)
        {
            length = -5;
        }
        else if(value > -1000000 && value <= -100000)
        {
            length = -6;
        }
        else if(value > -10000000 && value <= -1000000)
        {
            length = -7;
        }
        else if(value > -100000000 && value <= -10000000)
        {
            length = -8;
        }
        else if(value > -1000000000 && value <= -100000000)
        {
            length = -9;
        }
        else if(value <= -1000000000)
        {
            length = -10;
        }
        for(offset -= length, int index = 0; index-- > length; value /= 10)
        {
            text[offset + index] = (char) ('0' - value % 10);
        }
        fldOffset = offset;
        return this;
    }

    public AssemblerElementWriter writeString(CharSequence string) {
        int offset = fldOffset;
        string.copyInto(fldText, offset);
        fldOffset = offset + string.length;
        return this;
    }

    public AssemblerElementWriter writeString(CharSequence string, int beginIndex, int endIndex) {
        int offset = fldOffset;
        string.getChars(beginIndex, endIndex, fldText, offset);
        fldOffset = offset - beginIndex + endIndex;
        return this;
    }

    public AssemblerElementWriter writeLabel(Node node) {
        int label = node.debugIndex;
        return label >= 0 ? writeLabel('D', label) : writeLabel('L', node.labelIndex);
    }

    public AssemblerElementWriter writeSignature(int kind, int flags) {
        String signature;
        switch(kind)
        {
        case REF:
            signature = (flags & WEAK) != 0 ? "w" : "r";
            break;
        case BOOLEAN:
            signature = (flags & STACK) != 0 ? "i" : "b";
            break;
        case CHAR:
            signature = (flags & STACK) != 0 ? "i" : "c";
            break;
        case REAL:
            signature = "e";
            break;
        case DOUBLE:
            signature = "d";
            break;
        case DOUBLE2:
            signature = "d2";
            break;
        case DOUBLE4:
            signature = "d4";
            break;
        case DOUBLE8:
            signature = "d8";
            break;
        case FLOAT:
            signature = "f";
            break;
        case FLOAT2:
            signature = "f2";
            break;
        case FLOAT4:
            signature = "f4";
            break;
        case FLOAT8:
            signature = "f8";
            break;
        case BYTE:
            signature = (flags & STACK) != 0 ? "i" : "b";
            break;
        case BYTE2:
            signature = "b2";
            break;
        case BYTE4:
            signature = "b4";
            break;
        case BYTE8:
            signature = "b8";
            break;
        case SHORT:
            signature = (flags & STACK) != 0 ? "i" : "s";
            break;
        case SHORT2:
            signature = "s2";
            break;
        case SHORT4:
            signature = "s4";
            break;
        case SHORT8:
            signature = "s8";
            break;
        case INT:
            signature = "i";
            break;
        case INT2:
            signature = "i2";
            break;
        case INT4:
            signature = "i4";
            break;
        case INT8:
            signature = "i8";
            break;
        case LONG:
            signature = "l";
            break;
        case LONG2:
            signature = "l2";
            break;
        case LONG4:
            signature = "l4";
            break;
        case LONG8:
            signature = "l8";
            break;
        default:
            signature = "";
        }
        return writeString(signature);
    }

    public AssemblerElementWriter writeSignature(Type type, int flags) {
        String signature;
        switch(type.kind)
        {
        case REF:
            signature = (flags & WEAK) != 0 ? "w" : "r";
            break;
        case BOOLEAN:
            signature = (flags & STACK) != 0 ? "i" : "b";
            break;
        case CHAR:
            signature = (flags & STACK) != 0 ? "i" : "c";
            break;
        case REAL:
            signature = "e";
            break;
        case DOUBLE:
            signature = "d";
            break;
        case DOUBLE2:
            signature = "d2";
            break;
        case DOUBLE4:
            signature = "d4";
            break;
        case DOUBLE8:
            signature = "d8";
            break;
        case FLOAT:
            signature = "f";
            break;
        case FLOAT2:
            signature = "f2";
            break;
        case FLOAT4:
            signature = "f4";
            break;
        case FLOAT8:
            signature = "f8";
            break;
        case BYTE:
            signature = (flags & STACK) != 0 ? "i" : "b";
            break;
        case BYTE2:
            signature = "b2";
            break;
        case BYTE4:
            signature = "b4";
            break;
        case BYTE8:
            signature = "b8";
            break;
        case SHORT:
            signature = (flags & STACK) != 0 ? "i" : "s";
            break;
        case SHORT2:
            signature = "s2";
            break;
        case SHORT4:
            signature = "s4";
            break;
        case SHORT8:
            signature = "s8";
            break;
        case INT:
            signature = "i";
            break;
        case INT2:
            signature = "i2";
            break;
        case INT4:
            signature = "i4";
            break;
        case INT8:
            signature = "i8";
            break;
        case LONG:
            signature = "l";
            break;
        case LONG2:
            signature = "l2";
            break;
        case LONG4:
            signature = "l4";
            break;
        case LONG8:
            signature = "l8";
            break;
        default:
            signature = "";
        }
        return writeString(signature);
    }

    public final AssemblerElementWriter set(char[] dst) { return set(dst, 0); }

    public final int offset { read = fldOffset, write = fldOffset }
}