Skip to content

Commit 73d03c8

Browse files
authored
Save last element in stackframes for stacktraces (#1133)
1 parent d3c918b commit 73d03c8

File tree

4 files changed

+74
-24
lines changed

4 files changed

+74
-24
lines changed

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/EvaluateExpr.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
public class EvaluateExpr {
2424

25+
private static void mark(Element e, ProgramState globalState) {
26+
globalState.setLastElement(e);
27+
}
28+
2529
public static ILconst eval(ImBoolVal e, ProgramState globalState, LocalState localState) {
2630
return ILconstBool.instance(e.getValB());
2731
}
@@ -31,6 +35,8 @@ public static ILconst eval(ImFuncRef e, ProgramState globalState, LocalState loc
3135
}
3236

3337
public static @Nullable ILconst eval(ImFunctionCall e, ProgramState globalState, LocalState localState) {
38+
mark(e, globalState);
39+
3440
ImFunction f = e.getFunc();
3541
ImExprs arguments = e.getArguments();
3642

@@ -191,6 +197,7 @@ public static ILconst eval(ImVarArrayAccess e, ProgramState globalState, LocalSt
191197
ProgramState globalState, LocalState localState) {
192198
ILconstObject receiver = globalState.toObject(mc.getReceiver().evaluate(globalState, localState));
193199
globalState.assertAllocated(receiver, mc.attrTrace());
200+
mark(mc, globalState);
194201

195202
List<ImExpr> args = mc.getArguments();
196203

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ILInterpreter.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ public static LocalState runFunc(ProgramState globalState, ImFunction f, @Nullab
9797
if (args.length > 0 && args[0] instanceof ILconstObject) {
9898
receiverObj = (ILconstObject) args[0];
9999
}
100+
if (caller != null) {
101+
globalState.setLastElement(caller);
102+
}
100103
WPos pos = (caller != null) ? caller.attrTrace().attrErrorPos() : f.attrTrace().attrErrorPos();
101104
globalState.pushStackframeWithTypes(f, receiverObj, args, pos, normalized);
102105
try {
@@ -174,7 +177,9 @@ public static LocalState runFunc(ProgramState globalState, ImFunction f, @Nullab
174177
normalized.put(e.getKey(), rhs);
175178
}
176179

177-
// --- single push/pop responsibility ---
180+
if (caller != null) {
181+
globalState.setLastElement(caller);
182+
}
178183
WPos pos = (caller != null) ? caller.attrTrace().attrErrorPos() : f.attrTrace().attrErrorPos();
179184
globalState.pushStackframeWithTypes(f, receiverObj, args, pos, normalized);
180185

@@ -226,16 +231,36 @@ public static de.peeeq.wurstscript.ast.Element getTrace(ProgramState globalState
226231

227232
public static String buildStacktrace(ProgramState globalState, Throwable e) {
228233
StringBuilder err = new StringBuilder();
234+
229235
try {
230-
WPos src = globalState.getLastStatement().attrTrace().attrSource();
231-
err.append("Trace : ").append(new File(src.getFile()).getName()).append(":").append(src.getLine()).append("\n");
232-
} catch (Exception _e) {
236+
ILStackFrame top = globalState.getStackFrames().getStackFrames().isEmpty()
237+
? null
238+
: globalState.getStackFrames().getStackFrames().get(0);
239+
240+
WPos src = null;
241+
if (top != null) {
242+
src = top.getCurrentSourcePos();
243+
}
244+
if (src == null && globalState.getLastStatement() != null) {
245+
src = globalState.getLastStatement().attrTrace().attrSource();
246+
}
247+
248+
if (src != null) {
249+
err.append("Trace : ")
250+
.append(new File(src.getFile()).getName())
251+
.append(":")
252+
.append(src.getLine())
253+
.append("\n");
254+
}
255+
} catch (Exception ignored) {
233256
// ignore
234257
}
258+
235259
globalState.getStackFrames().appendTo(err);
236260
return err.toString();
237261
}
238262

263+
239264
@SuppressWarnings("null")
240265
private static ILconst adjustTypeOfConstant(@Nullable ILconst retVal, ImType expectedType) {
241266
if (retVal instanceof ILconstInt && isTypeReal(expectedType)) {

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ILStackFrame.java

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@
1313
import java.util.Map;
1414

1515
public class ILStackFrame {
16-
1716
public final Either<ImFunction, ImCompiletimeExpr> f;
1817
public final ILconst[] args;
1918
public final WPos trace;
2019
public final @Nullable ILconstObject receiver;
2120
public final Map<ImTypeVar, ImType> typeSubstitutions;
2221

23-
public ILStackFrame(ImFunction f, @Nullable ILconstObject receiver, ILconst[] args2, WPos trace, Map<ImTypeVar, ImType> typeSubstitutions) {
22+
// last executed element *within this frame*
23+
public @Nullable de.peeeq.wurstscript.jassIm.Element currentElement;
24+
25+
public ILStackFrame(ImFunction f, @Nullable ILconstObject receiver, ILconst[] args2, WPos trace,
26+
Map<ImTypeVar, ImType> typeSubstitutions) {
2427
this.f = Either.left(f);
2528
this.receiver = receiver;
2629
this.args = args2;
@@ -36,35 +39,40 @@ public ILStackFrame(ImCompiletimeExpr f, WPos trace) {
3639
this.typeSubstitutions = Collections.emptyMap();
3740
}
3841

42+
public @Nullable WPos getCurrentSourcePos() {
43+
if (currentElement != null) {
44+
try {
45+
return currentElement.attrTrace().attrSource();
46+
} catch (Exception ignored) {}
47+
}
48+
return trace;
49+
}
50+
3951
public String getMessage() {
4052
StringBuilder sb = new StringBuilder();
41-
if (trace != null && !trace.isArtificial()) {
42-
String file = new File(trace.getFile()).getName();
43-
sb.append(" ╚ ").append(file).append(":").append(trace.getLine());
53+
54+
WPos pos = getCurrentSourcePos();
55+
if (pos != null && !pos.isArtificial()) {
56+
String file = new File(pos.getFile()).getName();
57+
sb.append(" ╚ ").append(file).append(":").append(pos.getLine());
4458
}
59+
4560
if (f.isLeft()) {
46-
sb.append(" calling ").append(f.getLeft().getName()).append("(");
47-
boolean first = true;
48-
for (ILconst arg : args) {
49-
if (!first) {
50-
sb.append(", ");
51-
}
52-
sb.append(arg);
53-
first = false;
61+
sb.append(" inside call ").append(f.getLeft().getName()).append("(");
62+
for (int i = 0; i < args.length; i++) {
63+
if (i > 0) sb.append(", ");
64+
sb.append(args[i]);
5465
}
5566
sb.append(")");
5667
} else {
5768
sb.append("... when executing compiletime expression ");
5869
}
59-
6070
return sb.toString();
6171
}
6272

6373
public CompileError makeCompileError() {
64-
return new CompileError(trace, getMessage());
65-
}
66-
67-
public WPos getTrace() {
68-
return trace;
74+
// Use current element position if available:
75+
WPos pos = getCurrentSourcePos();
76+
return new CompileError(pos != null ? pos : trace, getMessage());
6977
}
7078
}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ProgramState.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,18 @@ private void identifyGenericStaticGlobals() {
118118
}
119119
}
120120

121+
public void setLastElement(de.peeeq.wurstscript.jassIm.Element e) {
122+
lastStatement = e;
123+
124+
ILStackFrame top = stackFrames.peek();
125+
if (top != null) {
126+
top.currentElement = e;
127+
}
128+
}
129+
130+
// keep old API, delegate:
121131
public void setLastStatement(ImStmt s) {
122-
lastStatement = s;
132+
setLastElement(s);
123133
}
124134

125135
public de.peeeq.wurstscript.jassIm.Element getLastStatement() {

0 commit comments

Comments
 (0)