stack traces

This commit is contained in:
Daniella / Tove 2022-05-26 19:21:29 +02:00
parent e819187cbd
commit 0a3c1bd60f
2 changed files with 96 additions and 17 deletions

View file

@ -35,7 +35,7 @@ public class ISBPL {
static boolean debug = false, printCalls = false;
public ISBPLDebugger.IPC debuggerIPC = new ISBPLDebugger.IPC();
ArrayList<ISBPLType> types = new ArrayList<>();
ISBPLFrame level0 = new ISBPLFrame(this);
ISBPLFrame level0 = new ISBPLFrame("isbpl", this);
final ISBPLThreadLocal<Stack<File>> fileStack = ISBPLThreadLocal.withInitial(Stack::new);
final ISBPLThreadLocal<Stack<ISBPLFrame>> frameStack = ISBPLThreadLocal.withInitial(() -> {
Stack<ISBPLFrame> frames = new Stack<>();
@ -48,6 +48,7 @@ public class ISBPL {
ArrayList<String> included = new ArrayList<>();
HashMap<String, ISBPLCallable> natives = new HashMap<>();
boolean stopExceptions = false;
HashMap<Throwable, Stack<ISBPLFrame>> stackTraces = new HashMap<>();
private final Object syncMakeThread = new Object();
private ISBPLKeyword getKeyword(String word) {
@ -70,7 +71,7 @@ public class ISBPL {
return (idx, words, file, stack) -> {
idx++;
AtomicInteger i = new AtomicInteger(idx);
ISBPLCallable callable = readCallable(i, words, file);
ISBPLCallable callable = readCallable("if", i, words, file);
if(stack.pop().isTruthy()) {
callable.call(stack);
}
@ -80,9 +81,9 @@ public class ISBPL {
return (idx, words, file, stack) -> {
idx++;
AtomicInteger i = new AtomicInteger(idx);
ISBPLCallable cond = readCallable(i, words, file);
ISBPLCallable cond = readCallable("while-condition", i, words, file);
i.getAndIncrement();
ISBPLCallable block = readCallable(i, words, file);
ISBPLCallable block = readCallable("while", i, words, file);
cond.call(stack);
while (stack.pop().isTruthy()) {
block.call(stack);
@ -115,14 +116,15 @@ public class ISBPL {
}
}
AtomicInteger i = new AtomicInteger(idx);
ISBPLCallable block = readCallable(i, words, file);
ISBPLCallable block = readCallable("try", i, words, file);
i.getAndIncrement();
ISBPLCallable catcher = readCallable(i, words, file);
ISBPLCallable catcher = readCallable("catch", i, words, file);
int stackHeight = stack.size();
try {
block.call(stack);
} catch (ISBPLError error) {
if (Arrays.asList(allowed).contains(error.type) || allowed.length == 1 && allowed[0].equals("all")) {
stack.push(new ISBPLObject(getType("error"), error));
stack.push(toISBPLString(error.message));
stack.push(toISBPLString(error.type));
catcher.call(stack);
@ -132,9 +134,11 @@ public class ISBPL {
}
} catch (Exception e) {
if (Arrays.asList(allowed).contains("Java") || allowed.length == 1 && allowed[0].equals("all")) {
stack.push(new ISBPLObject(getType("error"), e));
stack.push(toISBPL(e));
stack.push(toISBPLString(e.getClass().getName()));
stack.push(toISBPLString("Java"));
catcher.call(stack);
}
else {
throw e;
@ -154,9 +158,9 @@ public class ISBPL {
return (idx, words, file, stack) -> {
idx++;
AtomicInteger i = new AtomicInteger(idx);
ISBPLCallable block = readCallable(i, words, file);
ISBPLCallable block = readCallable("do-main", i, words, file);
i.getAndIncrement();
ISBPLCallable catcher = readCallable(i, words, file);
ISBPLCallable catcher = readCallable("do-finally", i, words, file);
try {
block.call(stack);
} finally {
@ -168,7 +172,7 @@ public class ISBPL {
case "{":
return (idx, words, file, stack) -> {
AtomicInteger i = new AtomicInteger(idx);
ISBPLCallable block = readCallable(i, words, file);
ISBPLCallable block = readCallable("lambda", i, words, file);
stack.push(new ISBPLObject(getType("func"), block));
return i.get();
};
@ -181,7 +185,7 @@ public class ISBPL {
for(ISBPLObject obj : stack) {
s.push(obj);
}
ISBPLCallable block = readCallable(i, words, file);
ISBPLCallable block = readCallable("thread", i, words, file);
long tid = Thread.currentThread().getId();
Stack<ISBPLFrame> fstack = (Stack<ISBPLFrame>) frameStack.get().clone();
new Thread(() -> {
@ -234,7 +238,7 @@ public class ISBPL {
if(definingMethods) {
AtomicInteger idx2 = new AtomicInteger(++j);
addFunction(type, word2, readCallable(idx2, words2, file));
addFunction(type, word2, readCallable(word2, idx2, words2, file));
j = idx2.get();
}
else {
@ -1099,6 +1103,25 @@ public class ISBPL {
}
};
break;
case "error.stacktrace":
func = (stack) -> {
ISBPLObject error = stack.pop();
error.checkType(getType("error"));
Throwable t = (Throwable) error.object;
Stack<ISBPLFrame> frames = stackTraces.get(t);
ISBPLObject[] array = new ISBPLObject[frames.size()];
for(int i = 0; i < frames.size(); i++) {
ISBPLFrame frame = frames.get(i);
ArrayList<ISBPLObject> arr = new ArrayList<>();
while(frame != null) {
arr.add(toISBPLString(frame.name));
frame = frame.parent;
}
array[i] = new ISBPLObject(getType("array"), arr.toArray(new ISBPLObject[0]));
}
stack.push(new ISBPLObject(getType("array"), array));
};
break;
default:
func = natives.get(name);
break;
@ -1422,7 +1445,7 @@ public class ISBPL {
i++;
String name = words[i];
AtomicInteger integer = new AtomicInteger(++i);
ISBPLCallable callable = readCallable(integer, words, file);
ISBPLCallable callable = readCallable(name, integer, words, file);
i = integer.get();
frameStack.get().peek().add(name, callable);
return i;
@ -1447,12 +1470,12 @@ public class ISBPL {
return newWords.toArray(new String[0]);
}
private ISBPLCallable readCallable(AtomicInteger idx, String[] words, File file) {
private ISBPLCallable readCallable(String name, AtomicInteger idx, String[] words, File file) {
String[] theWords = readBlock(idx, words, file);
ISBPLFrame frame = frameStack.get().peek();
return (stack) -> {
fileStack.get().push(file);
frameStack.get().push(new ISBPLFrame(this, frame));
frameStack.get().push(new ISBPLFrame(name, this, frame));
try {
interpretRaw(theWords, stack);
} finally {
@ -1613,9 +1636,12 @@ public class ISBPL {
e.printStackTrace();
}
catch (Throwable t) {
if(stackTraces.get(t) == null)
stackTraces.put(t, (Stack<ISBPLFrame>)frameStack.get().clone());
if(debug) ISBPL.gOutputStream.println("Passing exception " + t + " to caller.");
if(stopExceptions) {
t.printStackTrace();
ISBPL.gOutputStream.println(printStackTrace(stackTraces.get(t)));
ISBPL.gOutputStream.println("Current Words: ");
ISBPL.gOutputStream.println(Arrays.toString(words));
dump(stack);
@ -1624,6 +1650,24 @@ public class ISBPL {
}
}
public String printStackTrace(Stack<ISBPLFrame> frameStack) {
String s = "INTERPRET";
try {
String indent = " ";
for (ISBPLFrame frame : frameStack) {
s += "\n" + indent + "\\ ";
String p = "";
while(frame != null) {
p = "/" + frame.name + p;
frame = frame.parent;
}
s += p;
indent += " ";
}
} catch(Throwable t) { t.printStackTrace(); }
return s;
}
// Magic, please test before pushing changes!
private String[] splitWords(String code) {
ArrayList<String> words = new ArrayList<>();
@ -1765,14 +1809,16 @@ public class ISBPL {
ISBPL.gOutputStream.println("Error: " + e.type + ": " + e.message);
} catch(Throwable e) {
e.printStackTrace();
ISBPL.gErrorStream.println(isbpl.printStackTrace(isbpl.stackTraces.get(e)));
}
ISBPL.gOutputStream.print("\n> ");
}
}
} catch (ISBPLStop stop) {
System.exit(isbpl.exitCode);
} catch (Exception e) {
} catch (Throwable e) {
e.printStackTrace();
ISBPL.gErrorStream.println(isbpl.printStackTrace(isbpl.stackTraces.get(e)));
ISBPL.gOutputStream.println(stack);
}
}
@ -2426,11 +2472,14 @@ class ISBPLFrame {
public ISBPLFrame parent;
public HashMap<String, ISBPLCallable> map = new HashMap<>();
public HashMap<Object, ISBPLObject> variables = new HashMap<>();
public String name;
public ISBPLFrame(ISBPL context) {
public ISBPLFrame(String name, ISBPL context) {
this.name = name;
this.context = context;
}
public ISBPLFrame(ISBPL context, ISBPLFrame parentFrame) {
public ISBPLFrame(String name, ISBPL context, ISBPLFrame parentFrame) {
this.name = name;
this.context = context;
parent = parentFrame;
}

View file

@ -109,6 +109,19 @@ native null
def TYPE_FUNCTION "func" mktype =TYPE_FUNCTION
def Function TYPE_FUNCTION =Function
def Error construct error {
;
construct {
with id message this ;
id message throw
this
}
stacktrace {
native error.stacktrace
error.stacktrace
}
} =Error
def TYPE_ARRAY construct array {
;
construct {
@ -120,6 +133,23 @@ def TYPE_ARRAY construct array {
def i 0 =i
while { i this alen lt } { this i aget lambda fcall i ++ =i }
}
stackTraceToString {
def this =this
def s "INTERPRET" =s
def ind " " =ind
{
with element ;
s "\n" ind "\\ " strconcat strconcat strconcat =s
def p "" =p
{
with name ;
"/" name p strconcat strconcat =p
} element foreach
s p strconcat =s
ind " " strconcat =ind
} this foreach
s
}
} =TYPE_ARRAY
def Array TYPE_ARRAY =Array
def TYPE_STRING construct string array {