Skip to content

Commit bea1c63

Browse files
committed
fix stack trace in eval - #10
1 parent dbdd572 commit bea1c63

File tree

2 files changed

+37
-48
lines changed

2 files changed

+37
-48
lines changed

src/main/java/org/perlonjava/runtime/ExceptionFormatter.java

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java.util.ArrayList;
66
import java.util.Arrays;
7+
import java.util.concurrent.atomic.AtomicInteger;
78

89
/**
910
* The ExceptionFormatter class provides utility methods for formatting exceptions.
@@ -38,44 +39,52 @@ public static Throwable findInnermostCause(Throwable t) {
3839
}
3940

4041
/**
41-
* Formats the stack trace of the given Throwable into a structured list.
42-
* This method emulates the Perl method "Carp::longmess".
43-
* It only includes stack trace elements that contain the method name "apply" and do not
44-
* originate from Java source files.
42+
* Formats the stack trace of a Throwable, replacing specific entries with artificial caller stack entries.
4543
*
4644
* @param t The Throwable whose stack trace is to be formatted.
47-
* @return A list of lists, where each inner list contains the package name, source file name,
48-
* and line number of a relevant stack trace element.
45+
* @return A list of lists, where each inner list represents a stack trace element with package name, source file, and line number.
4946
*/
5047
private static ArrayList<ArrayList<String>> formatThrowable(Throwable t) {
5148
ArrayList<ArrayList<String>> stackTrace = new ArrayList<>();
52-
53-
// System.out.println("innermostCause: "); innermostCause.printStackTrace();
54-
55-
// Filter and append the stack trace
56-
57-
// Filter compiled Perl methods like:
58-
// org.perlonjava.anon1.apply(misc/snippets/CallerTest.pm @ CallerTest:36)
59-
// Filter `org.perlonjava.perlmodule` Perl-like Java methods like:
60-
// org.perlonjava.perlmodule.Exporter.exportOkTags(Exporter.java:159)
49+
AtomicInteger callerStackIndex = new AtomicInteger(); // Initialize the index for CallerStack
6150

6251
Arrays.stream(t.getStackTrace())
63-
.filter(element ->
64-
element.getClassName().contains("org.perlonjava.anon")
65-
|| element.getClassName().contains("org.perlonjava.perlmodule")
66-
)
6752
.forEach(element -> {
68-
ByteCodeSourceMapper.SourceLocation loc = ByteCodeSourceMapper.parseStackTraceElement(element);
69-
stackTrace.add(
70-
new ArrayList<>(
71-
Arrays.asList(
72-
loc.packageName(),
73-
loc.sourceFileName(),
74-
String.valueOf(loc.lineNumber())
53+
if (element.getClassName().equals("org.perlonjava.parser.StatementParser") &&
54+
element.getMethodName().equals("parseUseDeclaration")) {
55+
// Artificial caller stack entry created at `use` statement
56+
CallerStack.CallerInfo callerInfo = CallerStack.peek(callerStackIndex.get());
57+
if (callerInfo != null) {
58+
stackTrace.add(
59+
new ArrayList<>(
60+
Arrays.asList(
61+
callerInfo.packageName(),
62+
callerInfo.filename(),
63+
String.valueOf(callerInfo.line())
64+
)
7565
)
76-
)
77-
);
66+
);
67+
callerStackIndex.getAndIncrement(); // Increment the index for the next potential match
68+
}
69+
} else if (element.getClassName().contains("org.perlonjava.anon") ||
70+
element.getClassName().contains("org.perlonjava.perlmodule")) {
71+
// - Compiled Perl methods like:
72+
// org.perlonjava.anon1.apply(misc/snippets/CallerTest.pm @ CallerTest:36)
73+
// - Perl-like Java methods like:
74+
// org.perlonjava.perlmodule.Exporter.exportOkTags(Exporter.java:159)
75+
ByteCodeSourceMapper.SourceLocation loc = ByteCodeSourceMapper.parseStackTraceElement(element);
76+
stackTrace.add(
77+
new ArrayList<>(
78+
Arrays.asList(
79+
loc.packageName(),
80+
loc.sourceFileName(),
81+
String.valueOf(loc.lineNumber())
82+
)
83+
)
84+
);
85+
}
7886
});
87+
7988
return stackTrace;
8089
}
8190
}

src/main/java/org/perlonjava/runtime/RuntimeCode.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -326,13 +326,6 @@ public static RuntimeList caller(RuntimeList args, int ctx) {
326326
// for (int i = 0; i < stackTraceSize; i++) {
327327
// System.out.println("# " + i + ": " + stackTrace.get(i));
328328
// }
329-
// System.out.println("# CallerStack frames:");
330-
// for (int i = 0; i < 3; i++) {
331-
// CallerStack.CallerInfo info = CallerStack.peek(i);
332-
// if (info != null) {
333-
// System.out.println("# " + i + ": " + info);
334-
// }
335-
// }
336329
// System.out.println();
337330

338331
if (stackTraceSize > 0) {
@@ -347,19 +340,6 @@ public static RuntimeList caller(RuntimeList args, int ctx) {
347340
res.add(new RuntimeScalar(stackTrace.get(frame).get(1)));
348341
res.add(new RuntimeScalar(stackTrace.get(frame).get(2)));
349342
}
350-
} else {
351-
frame = frame - stackTraceSize;
352-
CallerStack.CallerInfo info = CallerStack.peek(frame);
353-
if (info != null) {
354-
// Compile-time stack trace
355-
if (ctx == RuntimeContextType.SCALAR) {
356-
res.add(new RuntimeScalar(info.packageName()));
357-
} else {
358-
res.add(new RuntimeScalar(info.packageName()));
359-
res.add(new RuntimeScalar(info.filename()));
360-
res.add(new RuntimeScalar(info.line()));
361-
}
362-
}
363343
}
364344
return res;
365345
}

0 commit comments

Comments
 (0)