Throwable.avt

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

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

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

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

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

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

package avt.lang;

import avt.io.*;

public class Throwable(Object)
{
    private static Throwable[] EMPTY_SUPPRESSED;

    private static native int suppressedCount();

    private long fldStackPointer;
    private long fldCodePointerOverride;
    private Throwable[] fldSuppressed;
    private StackTraceElement[] fldStackTrace;
    private String fldMessage;
    private Throwable fldCause;

    public (): this(null, null) {  }

    public (String message): this(message, null) {  }

    public (Throwable cause): this(null, cause) {  }

    public (String message, Throwable cause) {
        if(EMPTY_SUPPRESSED == null) (EMPTY_SUPPRESSED = new Throwable[0]).finalize();
        fldMessage = message;
        fldCause = cause;
    }

    package (String message, long codePointerOverride) {
        if(EMPTY_SUPPRESSED == null) (EMPTY_SUPPRESSED = new Throwable[0]).finalize();
        fldMessage = message;
        fldCodePointerOverride = codePointerOverride;
    }

    public String toString() {
        StringBuilder result = new StringBuilder() + getClass().canonicalName;
        String message = fldMessage;
        if(message != null)
        {
            message = message.trim();
            if(!message.isEmpty()) result + ": " + message;
        }
        return result.toString();
    }

    public final void printStackTrace() {
        System.err.print(stackTraceAsText());
    }

    public final void printStackTrace(PrintStream output) {
        (output != null ? output : System.err).print(stackTraceAsText());
    }

    public final Throwable[] suppressed { read = fldSuppressed }

    public final StackTraceElement[] stackTrace { read = fldStackTrace, write = setStackTrace }

    public final String message { read = fldMessage, write = fldMessage }

    public final Throwable cause { read = fldCause }

    protected void afterConstruction() {
        int length = suppressedCount();
        if(length <= 0)
        {
            fldSuppressed = EMPTY_SUPPRESSED;
        } else
        {
            Throwable[] suppressed = new Throwable[length];
            for(int index = 0; index < length; index++) suppressed[index] = index <= 0 ? findFirstSuppressed() : findNextSuppressed();
            suppressed.finalize();
            fldSuppressed = suppressed;
        }
        long codePointerOverride = fldCodePointerOverride;
        fldStackTrace = codePointerOverride == 0 ? Thread.stackTrace() : Thread.stackTrace(codePointerOverride);
    }

    protected CharSequence stackTraceAsText() {
        String at = package.getResourceString("string.throwable.at");
        String more = package.getResourceString("string.throwable.more");
        String cause = package.getResourceString("string.throwable.cause");
        String ellipsis = package.getResourceString("string.throwable.ellipsis");
        String suppressed = package.getResourceString("string.throwable.suppressed");
        String ending = Platform.instance.lineSeparator;
        StringBuilder result = new StringBuilder(0x7fff);
        for(Throwable[] supArray = fldSuppressed, int slength = supArray == null ? 0 : supArray.length, int sindex = -1; sindex < slength; sindex++)
        {
            Throwable current = sindex < 0 ? this : supArray[sindex];
            (current == this ? result : result + suppressed) + current + ending;
            StackTraceElement[] staArray = current.fldStackTrace;
            int alength = staArray == null ? 0 : staArray.length;
            for(int aindex = 0; aindex < alength; aindex++)
            {
                Object staElement = staArray[aindex];
                if(staElement != null) result + '\t' + at + staElement + ending;
            }
            for(Throwable curCause = current.fldCause; curCause != null; curCause = curCause.fldCause)
            {
                StackTraceElement[] stbArray = curCause.fldStackTrace;
                int blength = stbArray == null ? 0 : stbArray.length;
                int common = 0;
                for(int aindex = alength, int bindex = blength; aindex-- > 0 && bindex-- > 0; common++)
                {
                    Object staElement = staArray[aindex];
                    Object stbElement = stbArray[bindex];
                    if(staElement == null || stbElement == null || !staElement.equals(stbElement)) break;
                }
                result + cause + curCause + ending;
                for(int clength = blength - common, int cindex = 0; cindex < clength; cindex++)
                {
                    Object stbElement = stbArray[cindex];
                    if(stbElement != null) result + '\t' + at + stbElement + ending;
                }
                result + '\t' + ellipsis + common + more + ending;
                staArray = stbArray;
                alength = blength;
            }
        }
        return result;
    }

    private void setStackTrace(StackTraceElement[] newStackTrace) {
        if(newStackTrace == null)
        {
            fldStackTrace = null;
            return;
        }
        if(newStackTrace.isMutable())
        {
            (newStackTrace = (StackTraceElement[]) newStackTrace.clone()).finalize();
        }
        fldStackTrace = newStackTrace;
    }

    private native Throwable findFirstSuppressed();

    private native Throwable findNextSuppressed();
}