Skip to content

Commit 95c7175

Browse files
committed
Вывод информации о стеке вызовов при ошибке
1 parent cf6f8c5 commit 95c7175

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

src/com/annimon/ownlang/Main.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.annimon.ownlang;
22

3+
import com.annimon.ownlang.lib.CallStack;
4+
import com.annimon.ownlang.lib.Function;
5+
import com.annimon.ownlang.lib.Functions;
36
import com.annimon.ownlang.parser.Lexer;
47
import com.annimon.ownlang.parser.Parser;
58
import com.annimon.ownlang.parser.Token;
@@ -74,6 +77,18 @@ private static void run(String input, boolean showTokens, boolean showAst) {
7477
program.accept(new FunctionAdder());
7578
// program.accept(new VariablePrinter());
7679
program.accept(new AssignValidator());
77-
program.execute();
80+
try {
81+
program.execute();
82+
} catch (Exception ex) {
83+
handleException(Thread.currentThread(), ex);
84+
}
85+
}
86+
87+
public static void handleException(Thread thread, Throwable throwable) {
88+
System.err.printf("%s in %s\n", throwable.getMessage(), thread.getName());
89+
for (CallStack.CallInfo call : CallStack.getCalls()) {
90+
System.err.printf("\tat %s\n", call);
91+
}
92+
throwable.printStackTrace();
7893
}
7994
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.annimon.ownlang.lib;
2+
3+
import java.util.Deque;
4+
import java.util.concurrent.ConcurrentLinkedDeque;
5+
6+
public final class CallStack {
7+
8+
private static final Deque<CallInfo> calls = new ConcurrentLinkedDeque<CallInfo>();;
9+
10+
public static synchronized void enter(String name, Function function) {
11+
calls.push(new CallInfo(name, function));
12+
}
13+
14+
public static synchronized void exit() {
15+
calls.pop();
16+
}
17+
18+
public static synchronized Deque<CallInfo> getCalls() {
19+
return calls;
20+
}
21+
22+
public static class CallInfo {
23+
String name;
24+
Function function;
25+
26+
public CallInfo(String name, Function function) {
27+
this.name = name;
28+
this.function = function;
29+
}
30+
31+
@Override
32+
public String toString() {
33+
return String.format("%s: %s", name, function.toString().trim());
34+
}
35+
}
36+
}

src/com/annimon/ownlang/lib/modules/functions/std_thread.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.annimon.ownlang.lib.modules.functions;
22

3+
import com.annimon.ownlang.Main;
34
import com.annimon.ownlang.exceptions.ArgumentsMismatchException;
45
import com.annimon.ownlang.lib.*;
56

@@ -24,7 +25,9 @@ public Value execute(Value... args) {
2425
System.arraycopy(args, 1, params, 0, params.length);
2526
}
2627

27-
new Thread(() -> body.execute(params)).start();
28+
final Thread thread = new Thread(() -> body.execute(params));
29+
thread.setUncaughtExceptionHandler(Main::handleException);
30+
thread.start();
2831
return NumberValue.ZERO;
2932
}
3033
}

src/com/annimon/ownlang/parser/ast/FunctionalExpression.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ public Value eval() {
3131
for (int i = 0; i < size; i++) {
3232
values[i] = arguments.get(i).eval();
3333
}
34-
return consumeFunction(functionExpr).execute(values);
34+
final Function f = consumeFunction(functionExpr);
35+
CallStack.enter(functionExpr.toString(), f);
36+
final Value result = f.execute(values);
37+
CallStack.exit();
38+
return result;
3539
}
3640

3741
private Function consumeFunction(Expression expr) {

0 commit comments

Comments
 (0)