/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
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();
}