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

View file

@ -109,6 +109,19 @@ native null
def TYPE_FUNCTION "func" mktype =TYPE_FUNCTION def TYPE_FUNCTION "func" mktype =TYPE_FUNCTION
def Function TYPE_FUNCTION =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 { def TYPE_ARRAY construct array {
; ;
construct { construct {
@ -120,6 +133,23 @@ def TYPE_ARRAY construct array {
def i 0 =i def i 0 =i
while { i this alen lt } { this i aget lambda fcall i ++ =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 } =TYPE_ARRAY
def Array TYPE_ARRAY =Array def Array TYPE_ARRAY =Array
def TYPE_STRING construct string array { def TYPE_STRING construct string array {