Skip to content

Commit 9e09180

Browse files
committed
Fix for #5 (comment)
1 parent b6e67a2 commit 9e09180

File tree

4 files changed

+67
-19
lines changed

4 files changed

+67
-19
lines changed

build.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,28 @@
6666
<pathelement location="${dist}/CommunityModules-${timestamp}.jar" />
6767
</classpath>
6868
</java>
69+
70+
<!-- If an assert fails, TLC will return a non-zero exit value which is makes the ant target fail. -->
71+
<java classname="tlc2.TLC" fork="true" failonerror="true">
72+
<!-- Tell Java to use a garbage collector which makes TLC happy. -->
73+
<jvmarg value="-XX:+UseParallelGC"/>
74+
75+
<!-- Report execution statistics as azure-pipelien -->
76+
<sysproperty key="tlc2.TLC.ide" value="azure-pipeline"/>
77+
<sysproperty key="util.ExecutionStatisticsCollector.id" value="01ed03e40ba44f278a934849dd2b1038"/>
78+
79+
<arg value="-metadir"/>
80+
<arg value="${basedir}/build/states"/>
81+
<arg value="-cleanup"/>
82+
<arg value="-deadlock"/>
83+
<arg value="${basedir}/tests/GH005/TLCExtTrace"/>
84+
85+
<classpath>
86+
<pathelement location="${tlc}/tla2tools.jar" />
87+
<!-- The jar that has just been built by the dist target. -->
88+
<pathelement location="${dist}/CommunityModules-${timestamp}.jar" />
89+
</classpath>
90+
</java>
6991
</target>
7092

7193
<target name="clean" description="Delete the ${build}, ${tlc} and ${dist} directory trees">

modules/tlc2/overrides/TLCExt.java

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@
5454
public class TLCExt {
5555

5656
@Evaluation(definition = "AssertError", module = "TLCExt", warn = false)
57-
public synchronized static Value assertError(final Tool tool, final ExprOrOpArgNode[] args, final Context c, final TLCState s0,
58-
final TLCState s1, final int control, final CostModel cm) {
59-
57+
public synchronized static Value assertError(final Tool tool, final ExprOrOpArgNode[] args, final Context c,
58+
final TLCState s0, final TLCState s1, final int control, final CostModel cm) {
59+
6060
// Check expected err is a string.
6161
Assert.check(args[0] instanceof StringNode, "In computing AssertError, a non-string expression (" + args[0]
6262
+ ") was used as the err " + "of an AssertError(err, exp).");
63-
63+
6464
try {
6565
tool.eval(args[1], c, s0, s1, control, cm);
6666
} catch (EvalException e) {
@@ -71,15 +71,17 @@ public synchronized static Value assertError(final Tool tool, final ExprOrOpArgN
7171
}
7272
return BoolValue.ValFalse;
7373
}
74-
74+
7575
private static final Scanner scanner = new Scanner(System.in);
76-
77-
// This is likely only useful with a single worker, but let's synchronize anyway.
76+
77+
// This is likely only useful with a single worker, but let's synchronize
78+
// anyway.
7879
@Evaluation(definition = "PickSuccessor", module = "TLCExt", warn = false)
79-
public synchronized static Value pickSuccessor(final Tool tool, final ExprOrOpArgNode[] args, final Context c, final TLCState s0,
80-
final TLCState s1, final int control, final CostModel cm) {
81-
82-
// Eval expression and only let user interactively pick successor states when it evaluates to FALSE.
80+
public synchronized static Value pickSuccessor(final Tool tool, final ExprOrOpArgNode[] args, final Context c,
81+
final TLCState s0, final TLCState s1, final int control, final CostModel cm) {
82+
83+
// Eval expression and only let user interactively pick successor states when it
84+
// evaluates to FALSE.
8385
final Value guard = tool.eval(args[0], c, s0, s1, control, cm);
8486
if (!(guard instanceof BoolValue)) {
8587
Assert.fail("In evaluating TLCExt!PickSuccessor, a non-boolean expression (" + guard.getKindString()
@@ -88,9 +90,9 @@ public synchronized static Value pickSuccessor(final Tool tool, final ExprOrOpAr
8890
if (((BoolValue) guard).val) {
8991
return BoolValue.ValTrue;
9092
}
91-
93+
9294
// Find the (first) Action this pair of states belongs to. If more than one
93-
// Action match, we pick the first one.
95+
// Action match, we pick the first one.
9496
// TODO: This is clumsy (we regenerate all next-states again) and incorrect if
9597
// two actions generate the same successor states. It's good enough for now
9698
// until the Action instance was passed down the call-stack.
@@ -102,12 +104,14 @@ public synchronized static Value pickSuccessor(final Tool tool, final ExprOrOpAr
102104
break LOOP;
103105
}
104106
}
105-
107+
106108
while (true) {
107109
// TODO Add more commands such as continue/resume to pick every successor,
108-
// randomly pick next N successors, terminate to stop state space exploration, ...
110+
// randomly pick next N successors, terminate to stop state space exploration,
111+
// ...
109112
MP.printMessage(EC.TLC_MODULE_OVERRIDE_STDOUT,
110-
String.format("Extend behavior of length %s with a \"%s\" step [%s]? (Yes/no/explored/states/diff):",
113+
String.format(
114+
"Extend behavior of length %s with a \"%s\" step [%s]? (Yes/no/explored/states/diff):",
111115
s0.getLevel(), action.getName(), action));
112116

113117
final String nextLine = scanner.nextLine();
@@ -136,16 +140,23 @@ public synchronized static Value getTrace() throws IOException {
136140
final ModelChecker mc = (ModelChecker) TLCGlobals.mainChecker;
137141
final ConcurrentTLCTrace traceFile = mc.trace;
138142

143+
// If Trace operator is evaluated during the next-state relation, it will return
144+
// the state from which the next state is generated.
139145
final TLCState currentState = IdThread.getCurrentState();
140146
if (currentState == null) {
141147
return new TupleValue(new Value[0]);
142148
}
143-
149+
150+
if (currentState.isInitial()) {
151+
return new TupleValue(new Value[] { new RecordValue(currentState) });
152+
}
153+
144154
final TLCStateInfo[] trace = traceFile.getTrace(currentState);
145-
final Value[] values = new Value[trace.length];
146-
for (int j = 0; j < trace.length; j++) {
155+
final Value[] values = new Value[trace.length + 1];
156+
for (int j = 0; j < (trace.length); j++) {
147157
values[j] = new RecordValue(trace[j].state);
148158
}
159+
values[values.length - 1] = new RecordValue(currentState);
149160
return new TupleValue(values);
150161
}
151162
}

tests/GH005/TLCExtTrace.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
SPECIFICATION Spec
2+
INVARIANT Inv

tests/GH005/TLCExtTrace.tla

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---- MODULE TLCExtTrace ----
2+
3+
EXTENDS Integers, TLC, TLCExt
4+
5+
VARIABLE x
6+
7+
Spec == x = 1 /\ [][x < 10 /\ x' = x + 1]_x
8+
9+
Inv == \/ x = 1
10+
\/ PrintT(<<Trace, x>>)
11+
12+
==================================
13+

0 commit comments

Comments
 (0)