Skip to content

Commit ee3c6d6

Browse files
Support @proc@ for the -mv option (boogie-org#530)
1 parent a1faa69 commit ee3c6d6

File tree

14 files changed

+133
-108
lines changed

14 files changed

+133
-108
lines changed

Source/Core/Helpers.cs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
24
using System.Diagnostics.Contracts;
35

46
namespace Microsoft.Boogie
@@ -263,18 +265,30 @@ public static void ExtraTraceInformation(CoreOptions options, string point)
263265
}
264266
}
265267

266-
// Substitute @PROC@ in a filename with the given descName
267-
public static string SubstituteAtPROC(string descName, string fileName)
268+
private static readonly ConcurrentDictionary<string, int> UsedLogNames = new();
269+
public static (string fileName, bool reused) GetLogFilename(string descriptiveName, string filename, bool allowReuse)
268270
{
269-
Contract.Requires(fileName != null);
270-
Contract.Requires(descName != null);
271+
filename = SubstituteAtPROC(descriptiveName, cce.NonNull(filename));
272+
273+
var reused = false;
274+
var index = UsedLogNames.AddOrUpdate(filename, 0, (_, i) => {
275+
reused = allowReuse;
276+
return allowReuse ? i : i + 1;
277+
});
278+
var filenameWithIndex = index > 0 ? filename + "." + index : filename;
279+
280+
return (filenameWithIndex, reused);
281+
}
282+
283+
private static string SubstituteAtPROC(string descriptiveName, string filename)
284+
{
285+
Contract.Requires(filename != null);
286+
Contract.Requires(descriptiveName != null);
271287
Contract.Ensures(Contract.Result<string>() != null);
272-
System.Text.StringBuilder /*!*/
273-
sb =
274-
new System.Text.StringBuilder(descName.Length);
288+
var /*!*/ sb = new System.Text.StringBuilder(descriptiveName.Length);
275289
// quote the name, characters like ^ cause trouble in CMD
276290
// while $ could cause trouble in SH
277-
foreach (char c in descName)
291+
foreach (char c in descriptiveName)
278292
{
279293
if (Char.IsLetterOrDigit(c) || c == '.')
280294
{
@@ -291,13 +305,13 @@ public static string SubstituteAtPROC(string descName, string fileName)
291305
// do it by truncating the @PROC@ replacement, which leaves unchanged
292306
// any filename extension specified by the user. We base our
293307
// calculations on that there is at most one occurrence of @PROC@.
294-
if (180 <= fileName.Length - 6 + pn.Length)
308+
if (180 <= filename.Length - 6 + pn.Length)
295309
{
296-
pn = pn.Substring(0, Math.Max(180 - (fileName.Length - 6), 0)) + "-n" +
310+
pn = pn.Substring(0, Math.Max(180 - (filename.Length - 6), 0)) + "-n" +
297311
System.Threading.Interlocked.Increment(ref sequenceId);
298312
}
299313

300-
return fileName.Replace("@PROC@", pn);
314+
return filename.Replace("@PROC@", pn);
301315
}
302316

303317
private static int sequenceId = -1;

Source/ExecutionEngine/ConsolePrinter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public void WriteErrorInformation(ErrorInformation errorInfo, TextWriter tw, boo
142142
}
143143

144144
tw.Write(errorInfo.Out.ToString());
145-
tw.Write(errorInfo.Model.ToString());
145+
tw.Write(errorInfo.ModelWriter.ToString());
146146
tw.Flush();
147147
}
148148

Source/ExecutionEngine/ExecutionEngine.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public class ErrorInformation
9999
public ErrorKind Kind { get; set; }
100100
public string ImplementationName { get; set; }
101101
public TextWriter Out = new StringWriter();
102-
public TextWriter Model = new StringWriter();
102+
public TextWriter ModelWriter = new StringWriter();
103103

104104
public string FullMsg
105105
{
@@ -1501,7 +1501,7 @@ public void ProcessErrors(List<Counterexample> errors, VC.VCGen.Outcome outcome,
15011501
}
15021502

15031503
if (Options.ModelViewFile != null) {
1504-
error.PrintModel(errorInfo.Model, error);
1504+
error.PrintModel(errorInfo.ModelWriter, error);
15051505
}
15061506

15071507
printer.WriteErrorInformation(errorInfo, tw);
Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private Tuple<Variable, Variable> createNewExplainConstants(Variable v)
109109
}
110110

111111

112-
public class HoudiniSession
112+
public class HoudiniSession : ProofRun
113113
{
114114
public class HoudiniStatistics
115115
{
@@ -120,7 +120,7 @@ public class HoudiniStatistics
120120
public int numUnsatCorePrunings = 0;
121121
}
122122

123-
public string descriptiveName;
123+
public string Description { get; }
124124
private readonly Houdini houdini;
125125
public HoudiniStatistics stats;
126126
private VCExpr conjecture;
@@ -155,7 +155,7 @@ public bool InUnsatCore(Variable constant)
155155
public HoudiniSession(Houdini houdini, VCGen vcgen, ProverInterface proverInterface, Program program,
156156
Implementation impl, HoudiniStatistics stats, int taskID = -1)
157157
{
158-
this.descriptiveName = impl.Name;
158+
this.Description = impl.Name;
159159
this.houdini = houdini;
160160
this.stats = stats;
161161
collector = new ConditionGeneration.VerificationResultCollector(houdini.Options);
@@ -186,12 +186,12 @@ public HoudiniSession(Houdini houdini, VCGen vcgen, ProverInterface proverInterf
186186
VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(absyIds.GetId(impl.Blocks[0]))));
187187
conjecture = exprGen.Implies(eqExpr, conjecture);
188188

189-
Macro macro = new Macro(Token.NoToken, descriptiveName, new List<Variable>(),
189+
Macro macro = new Macro(Token.NoToken, Description, new List<Variable>(),
190190
new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Type.Bool), false));
191191
proverInterface.DefineMacro(macro, conjecture);
192192
conjecture = exprGen.Function(macro);
193193
handler = new VCGen.ErrorReporter(this.houdini.Options, gotoCmdOrigins, absyIds, impl.Blocks, vcgen.debugInfos, collector,
194-
mvInfo, proverInterface.Context, program);
194+
mvInfo, proverInterface.Context, program, this);
195195
}
196196

197197
private VCExpr BuildAxiom(ProverInterface proverInterface, Dictionary<Variable, bool> currentAssignment)
@@ -254,13 +254,13 @@ public ProverInterface.Outcome Verify(ProverInterface proverInterface, Dictionar
254254

255255
if (Options.Trace)
256256
{
257-
Console.WriteLine("Verifying " + descriptiveName);
257+
Console.WriteLine("Verifying " + Description);
258258
}
259259

260260
DateTime now = DateTime.UtcNow;
261261

262262
VCExpr vc = proverInterface.VCExprGen.Implies(BuildAxiom(proverInterface, assignment), conjecture);
263-
proverInterface.BeginCheck(descriptiveName, vc, handler);
263+
proverInterface.BeginCheck(Description, vc, handler);
264264
ProverInterface.Outcome proverOutcome = proverInterface.CheckOutcome(handler, errorLimit, CancellationToken.None).Result;
265265

266266
double queryTime = (DateTime.UtcNow - now).TotalSeconds;
@@ -380,7 +380,7 @@ public void Explain(ProverInterface proverInterface,
380380

381381
if (Options.Trace)
382382
{
383-
Console.WriteLine("Verifying (MaxSat) " + descriptiveName);
383+
Console.WriteLine("Verifying (MaxSat) " + Description);
384384
}
385385

386386
DateTime now = DateTime.UtcNow;
@@ -393,8 +393,8 @@ public void Explain(ProverInterface proverInterface,
393393
do
394394
{
395395
hardAssumptions.Add(controlExprNoop);
396-
(outcome, var unsatisfiedSoftAssumptions) = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions,
397-
handler, CancellationToken.None).Result;
396+
(outcome, var unsatisfiedSoftAssumptions) = proverInterface.CheckAssumptions(hardAssumptions,
397+
softAssumptions, handler, CancellationToken.None).Result;
398398
hardAssumptions.RemoveAt(hardAssumptions.Count - 1);
399399

400400
if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory ||
@@ -428,7 +428,7 @@ public void Explain(ProverInterface proverInterface,
428428
hardAssumptions.Add(softAssumptions[i]);
429429
}
430430

431-
(outcome, var unsatisfiedSoftAssumptions2) = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2,
431+
(outcome, var unsatisfiedSoftAssumptions2) = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2,
432432
handler, CancellationToken.None).Result;
433433

434434
if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory ||
@@ -451,22 +451,22 @@ public void Explain(ProverInterface proverInterface,
451451
foreach (var r in reason)
452452
{
453453
Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name,
454-
r, descriptiveName);
454+
r, Description);
455455
}
456456

457457
//also add the removed reasons using dotted edges (requires- x != 0, requires- x == 0 ==> assert x != 0)
458458
foreach (var r in reason1)
459459
{
460460
Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=blue style=dotted ];",
461-
refutedConstant.Name, r, descriptiveName);
461+
refutedConstant.Name, r, Description);
462462
}
463463
} while (false);
464464

465465
if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory ||
466466
outcome == ProverInterface.Outcome.OutOfResource || outcome == ProverInterface.Outcome.Undetermined)
467467
{
468468
Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name,
469-
"TimeOut", descriptiveName);
469+
"TimeOut", Description);
470470
}
471471

472472
Options.ErrorLimit = el;

Source/Provers/SMTLib/ProverInterface.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Diagnostics.Contracts;
44
using System.Threading;
55
using System.Threading.Tasks;
6+
using Microsoft.Boogie.SMTLib;
67
using Microsoft.Boogie.VCExprAST;
78

89
namespace Microsoft.Boogie;

Source/Provers/SMTLib/ProverUtil.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ public virtual TextWriter OpenLog(string /*?*/ descName)
298298
Contract.Assert(filename != null);
299299
if (descName != null)
300300
{
301-
filename = Helpers.SubstituteAtPROC(descName, filename);
301+
filename = Helpers.GetLogFilename(descName, filename, true).fileName;
302302
}
303303

304304
return new StreamWriter(filename, AppendLogFile);

Source/Provers/SMTLib/SMTLibProcessTheoremProver.cs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -524,22 +524,10 @@ protected TextWriter OpenOutputFile(string descriptiveName)
524524
Contract.Requires(descriptiveName != null);
525525
Contract.Ensures(Contract.Result<TextWriter>() != null);
526526

527-
string filename = options.LogFilename;
528-
filename = Helpers.SubstituteAtPROC(descriptiveName, cce.NonNull(filename));
529-
var curFilename = filename;
527+
string filenameTemplate = options.LogFilename;
528+
var (filename, reused) = Helpers.GetLogFilename(descriptiveName, filenameTemplate, false);
530529

531-
lock (usedLogNames)
532-
{
533-
int n = 1;
534-
while (usedLogNames.Contains(curFilename))
535-
{
536-
curFilename = filename + "." + n++;
537-
}
538-
539-
usedLogNames.Add(curFilename);
540-
}
541-
542-
return new StreamWriter(curFilename, false);
530+
return new StreamWriter(filename, reused);
543531
}
544532

545533
protected void FlushProverWarnings()

Source/VCGeneration/Checker.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Threading;
66
using Microsoft.Boogie.VCExprAST;
77
using System.Threading.Tasks;
8+
using Microsoft.Boogie.SMTLib;
89
using VC;
910

1011
namespace Microsoft.Boogie
@@ -261,7 +262,7 @@ public Task<int> GetProverResourceCount()
261262
return thmProver.GetRCount();
262263
}
263264

264-
private async Task WaitForOutput(object dummy, CancellationToken cancellationToken)
265+
private async Task WaitForOutput(CancellationToken cancellationToken)
265266
{
266267
try {
267268
outcome = await thmProver.CheckOutcome(cce.NonNull(handler), Options.ErrorLimit,
@@ -328,7 +329,7 @@ public void BeginCheck(string descriptiveName, VCExpr vc, ProverInterface.ErrorH
328329
thmProver.BeginCheck(descriptiveName, vc, handler);
329330
// gen.ClearSharedFormulas(); PR: don't know yet what to do with this guy
330331

331-
ProverTask = WaitForOutput(null, cancellationToken);
332+
ProverTask = WaitForOutput(cancellationToken);
332333
}
333334

334335
public ProverInterface.Outcome ReadOutcome()

Source/VCGeneration/Counterexample.cs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ void ObjectInvariant()
7474
Contract.Invariant(cce.NonNullDictionaryAndValues(calleeCounterexamples));
7575
}
7676

77+
public ProofRun ProofRun { get; }
7778
protected readonly VCGenOptions options;
7879
[Peer] public List<Block> Trace;
7980
public List<object> AugmentedTrace;
@@ -88,7 +89,8 @@ void ObjectInvariant()
8889

8990
public Dictionary<TraceLocation, CalleeCounterexampleInfo> calleeCounterexamples;
9091

91-
internal Counterexample(VCGenOptions options, List<Block> trace, List<object> augmentedTrace, Model model, VC.ModelViewInfo mvInfo, ProverContext context)
92+
internal Counterexample(VCGenOptions options, List<Block> trace, List<object> augmentedTrace, Model model,
93+
VC.ModelViewInfo mvInfo, ProverContext context, ProofRun proofRun)
9294
{
9395
Contract.Requires(trace != null);
9496
Contract.Requires(context != null);
@@ -97,6 +99,7 @@ internal Counterexample(VCGenOptions options, List<Block> trace, List<object> au
9799
this.Model = model;
98100
this.MvInfo = mvInfo;
99101
this.Context = context;
102+
this.ProofRun = proofRun;
100103
this.calleeCounterexamples = new Dictionary<TraceLocation, CalleeCounterexampleInfo>();
101104
// the call to instance method GetModelValue in the following code requires the fields Model and Context to be initialized
102105
if (augmentedTrace != null)
@@ -213,14 +216,12 @@ public void Print(int indent, TextWriter tw, Action<Block> blockAction = null)
213216
}
214217
}
215218

216-
public static bool firstModelFile = true;
217-
218219
public void PrintModel(TextWriter tw, Counterexample counterexample)
219220
{
220221
Contract.Requires(counterexample != null);
221222

222-
var filename = options.ModelViewFile;
223-
if (Model == null || filename == null || options.StratifiedInlining > 0)
223+
var filenameTemplate = options.ModelViewFile;
224+
if (Model == null || filenameTemplate == null || options.StratifiedInlining > 0)
224225
{
225226
return;
226227
}
@@ -238,14 +239,14 @@ public void PrintModel(TextWriter tw, Counterexample counterexample)
238239
Model.ModelHasStatesAlready = true;
239240
}
240241

241-
if (filename == "-")
242+
if (filenameTemplate == "-")
242243
{
243244
Model.Write(tw);
244245
tw.Flush();
245246
}
246247
else {
247-
using var wr = new StreamWriter(filename, !firstModelFile);
248-
firstModelFile = false;
248+
var (filename, reused) = Helpers.GetLogFilename(ProofRun.Description, filenameTemplate, true);
249+
using var wr = new StreamWriter(filename, reused);
249250
Model.Write(wr);
250251
}
251252
}
@@ -476,8 +477,8 @@ void ObjectInvariant()
476477

477478

478479
public AssertCounterexample(VCGenOptions options, List<Block> trace, List<object> augmentedTrace, AssertCmd failingAssert, Model model, VC.ModelViewInfo mvInfo,
479-
ProverContext context)
480-
: base(options, trace, augmentedTrace, model, mvInfo, context)
480+
ProverContext context, ProofRun proofRun)
481+
: base(options, trace, augmentedTrace, model, mvInfo, context, proofRun)
481482
{
482483
Contract.Requires(trace != null);
483484
Contract.Requires(failingAssert != null);
@@ -497,7 +498,7 @@ public override byte[] Checksum
497498

498499
public override Counterexample Clone()
499500
{
500-
var ret = new AssertCounterexample(options, Trace, AugmentedTrace, FailingAssert, Model, MvInfo, Context);
501+
var ret = new AssertCounterexample(options, Trace, AugmentedTrace, FailingAssert, Model, MvInfo, Context, ProofRun);
501502
ret.calleeCounterexamples = calleeCounterexamples;
502503
return ret;
503504
}
@@ -517,8 +518,8 @@ void ObjectInvariant()
517518

518519

519520
public CallCounterexample(VCGenOptions options, List<Block> trace, List<object> augmentedTrace, CallCmd failingCall, Requires failingRequires, Model model,
520-
VC.ModelViewInfo mvInfo, ProverContext context, byte[] checksum = null)
521-
: base(options, trace, augmentedTrace, model, mvInfo, context)
521+
VC.ModelViewInfo mvInfo, ProverContext context, ProofRun proofRun, byte[] checksum = null)
522+
: base(options, trace, augmentedTrace, model, mvInfo, context, proofRun)
522523
{
523524
Contract.Requires(!failingRequires.Free);
524525
Contract.Requires(trace != null);
@@ -545,7 +546,7 @@ public override byte[] Checksum
545546

546547
public override Counterexample Clone()
547548
{
548-
var ret = new CallCounterexample(options, Trace, AugmentedTrace, FailingCall, FailingRequires, Model, MvInfo, Context, Checksum);
549+
var ret = new CallCounterexample(options, Trace, AugmentedTrace, FailingCall, FailingRequires, Model, MvInfo, Context, ProofRun, Checksum);
549550
ret.calleeCounterexamples = calleeCounterexamples;
550551
return ret;
551552
}
@@ -565,8 +566,8 @@ void ObjectInvariant()
565566

566567

567568
public ReturnCounterexample(VCGenOptions options, List<Block> trace, List<object> augmentedTrace, TransferCmd failingReturn, Ensures failingEnsures, Model model,
568-
VC.ModelViewInfo mvInfo, ProverContext context, byte[] checksum)
569-
: base(options, trace, augmentedTrace, model, mvInfo, context)
569+
VC.ModelViewInfo mvInfo, ProverContext context, ProofRun proofRun, byte[] checksum)
570+
: base(options, trace, augmentedTrace, model, mvInfo, context, proofRun)
570571
{
571572
Contract.Requires(trace != null);
572573
Contract.Requires(context != null);
@@ -595,7 +596,7 @@ public override byte[] Checksum
595596

596597
public override Counterexample Clone()
597598
{
598-
var ret = new ReturnCounterexample(options, Trace, AugmentedTrace, FailingReturn, FailingEnsures, Model, MvInfo, Context, checksum);
599+
var ret = new ReturnCounterexample(options, Trace, AugmentedTrace, FailingReturn, FailingEnsures, Model, MvInfo, Context, ProofRun, checksum);
599600
ret.calleeCounterexamples = calleeCounterexamples;
600601
return ret;
601602
}

Source/VCGeneration/ProofRun.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace VC;
2+
3+
public interface ProofRun {
4+
string Description { get; }
5+
}

0 commit comments

Comments
 (0)