Throwable.avt

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

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

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

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии 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 (Throwable cause): this(null, cause) {  }

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

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

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

    public String toString() {
        StringBuilder result = (new StringBuilder()).append(getClass().canonicalName);
        String message = fldMessage;
        if(message != null)
        {
            message = message.trim();
            if(!message.isEmpty()) result.append(": ").append(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 StackTraceElement[] stackTrace { read = fldStackTrace, write = setStackTrace }

    public final Throwable[] suppressed { read = fldSuppressed }

    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 codePtrOverride = fldCodePointerOverride;
        fldStackTrace = codePtrOverride == 0 ? Thread.stackTrace() : Thread.stackTrace(codePtrOverride);
    }

    protected String 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 supLength = supArray == null ? 0 : supArray.length, int supIndex = -1; supIndex < supLength; supIndex++)
        {
            Throwable current = supIndex < 0 ? this : supArray[supIndex];
            (current == this ? result : result.append(suppressed)).append(current).append(ending);
            StackTraceElement[] staArray = current.fldStackTrace;
            int staLength = staArray == null ? 0 : staArray.length;
            for(int staIndex = 0; staIndex < staLength; staIndex++)
            {
                Object staElement = staArray[staIndex];
                if(staElement != null) result.append('\t').append(at).append(staElement).append(ending);
            }
            for(Throwable curCause = current.fldCause; curCause != null; curCause = curCause.fldCause)
            {
                StackTraceElement[] stbArray = curCause.fldStackTrace;
                int stbLength = stbArray == null ? 0 : stbArray.length;
                int common = 0;
                for(int staIndex = staLength, int stbIndex = stbLength; staIndex-- > 0 && stbIndex-- > 0; common++)
                {
                    Object staElement = staArray[staIndex];
                    Object stbElement = stbArray[stbIndex];
                    if(staElement == null || stbElement == null || !staElement.equals(stbElement)) break;
                }
                result.append(cause).append(curCause).append(ending);
                for(int comLength = stbLength - common, int comIndex = 0; comIndex < comLength; comIndex++)
                {
                    Object stbElement = stbArray[comIndex];
                    if(stbElement != null) result.append('\t').append(at).append(stbElement).append(ending);
                }
                result.append('\t').append(ellipsis).append(common).append(more).append(ending);
                staArray = stbArray;
                staLength = stbLength;
            }
        }
        return result.toString();
    }

    private void setStackTrace(StackTraceElement[] newStackTrace) {
        if(newStackTrace == null)
        {
            fldStackTrace = null;
            return;
        }
        int length = newStackTrace.length;
        if(length < newStackTrace.capacity) Array.copy(newStackTrace, 0, newStackTrace = new StackTraceElement[length], 0, length);
        fldStackTrace = newStackTrace;
    }

    private native Throwable findFirstSuppressed();

    private native Throwable findNextSuppressed();
}