stack traces
This commit is contained in:
parent
e819187cbd
commit
0a3c1bd60f
2 changed files with 96 additions and 17 deletions
83
ISBPL.java
83
ISBPL.java
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
30
std.isbpl
30
std.isbpl
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue