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;
|
||||
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);
|
||||
|
@ -1623,6 +1649,24 @@ public class ISBPL {
|
|||
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!
|
||||
private String[] splitWords(String code) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
30
std.isbpl
30
std.isbpl
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue