Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce {:isolate} and {:isolate "paths"} attributes for assert and return commands #952

Open
wants to merge 61 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
576e153
IsolatePaths option seems to work, although it still duplicates errors
keyboardDrummer Sep 24, 2024
8d0bee6
Refactoring
keyboardDrummer Sep 24, 2024
0465e6e
Finish test and some more refactoring
keyboardDrummer Sep 24, 2024
b451f9f
Refactoring
keyboardDrummer Sep 24, 2024
b016f40
Refactoring
keyboardDrummer Sep 24, 2024
0fa1817
Update version number
keyboardDrummer Sep 24, 2024
4755839
Tweaks
keyboardDrummer Sep 24, 2024
23f44ed
Improve implementation and add tests
keyboardDrummer Sep 24, 2024
64b1010
More efficient assumed block generation
keyboardDrummer Sep 25, 2024
bccf0b1
Improvements to splitting, but still need check command to make the t…
keyboardDrummer Sep 25, 2024
7d5b58f
Some changes
keyboardDrummer Sep 27, 2024
a2f1f76
Remove isolatePaths code
keyboardDrummer Sep 27, 2024
9620a3f
Add path tokens
keyboardDrummer Sep 27, 2024
c5f13f0
Refactoring
keyboardDrummer Sep 27, 2024
409cdb8
Rename
keyboardDrummer Sep 27, 2024
d4d5db6
Refactoring
keyboardDrummer Sep 27, 2024
627b42c
Upgrade token
keyboardDrummer Sep 27, 2024
b6e6dab
Fixes
keyboardDrummer Sep 27, 2024
d08537e
Introduce ImplementationPartToken
keyboardDrummer Sep 27, 2024
b46af73
Rename
keyboardDrummer Sep 27, 2024
6718564
Refactoring
keyboardDrummer Sep 27, 2024
23a0942
Refactoring
keyboardDrummer Sep 27, 2024
2404e95
Fix warnings
keyboardDrummer Sep 27, 2024
d847412
Draft for isolated assertion
keyboardDrummer Sep 30, 2024
dea7493
More progress on the {:isolate} attribute
keyboardDrummer Sep 30, 2024
cf450a1
Move some code into DesugarReturns
keyboardDrummer Oct 1, 2024
6c8ccaf
Work on supporting isolate for return commands
keyboardDrummer Oct 1, 2024
5bbe971
Refactoring
keyboardDrummer Oct 1, 2024
0d0e8fc
Reorder tests
keyboardDrummer Oct 1, 2024
a73bba0
Fixes. Isolatepaths for assertions seems to work
keyboardDrummer Oct 1, 2024
9a3ee51
Added isolateJump test
keyboardDrummer Oct 1, 2024
9ebb0a2
Update tests and fixes
keyboardDrummer Oct 2, 2024
b7c9f8d
Merge commit '40f15f1e1~1' into isolatePaths
keyboardDrummer Oct 2, 2024
5372d5e
Merge commit '40f15f1e1' into isolatePaths
keyboardDrummer Oct 2, 2024
db79862
Code review
keyboardDrummer Oct 2, 2024
206acde
Add refactoring
keyboardDrummer Oct 2, 2024
617852b
Refactoring
keyboardDrummer Oct 2, 2024
2886d7e
Fix
keyboardDrummer Oct 2, 2024
feeda38
Update test
keyboardDrummer Oct 2, 2024
1ae99e3
Fix test
keyboardDrummer Oct 2, 2024
2547c87
Save
keyboardDrummer Oct 2, 2024
24e5b4d
Extract some code into file RemoveBackEdges
keyboardDrummer Oct 2, 2024
cc96494
Remove need for gotoCmdOrigins map
keyboardDrummer Oct 2, 2024
6797249
Remove occurrences of gotoCmd dictionary
keyboardDrummer Oct 2, 2024
d3a9015
Simple fail now passes
keyboardDrummer Oct 2, 2024
c1db5a2
Update test files
keyboardDrummer Oct 2, 2024
064b44a
Fixes
keyboardDrummer Oct 2, 2024
a7ce5e0
Test file fixes
keyboardDrummer Oct 2, 2024
9a27654
Fixes
keyboardDrummer Oct 3, 2024
43d6824
Update tests
keyboardDrummer Oct 3, 2024
1a5ff89
Fix path isolation error reporting
keyboardDrummer Oct 3, 2024
be86f19
Refactoring
keyboardDrummer Oct 3, 2024
d91787c
Refactoring
keyboardDrummer Oct 3, 2024
2e8c8e4
Remove TODO
keyboardDrummer Oct 3, 2024
91c304d
Refactoring
keyboardDrummer Oct 3, 2024
ff1442a
Remove TODO
keyboardDrummer Oct 3, 2024
c603cc8
Cleanup
keyboardDrummer Oct 3, 2024
e3a6d66
Merge commit '9a8ce8d4c4c' into isolatePaths
keyboardDrummer Oct 3, 2024
d09374c
Update Source/Directory.Build.props
keyboardDrummer Oct 4, 2024
7db5dee
Refactorings
keyboardDrummer Oct 4, 2024
8ea0f08
Merge branch 'isolatePaths' of github.com:keyboardDrummer/boogie into…
keyboardDrummer Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions Source/Core/AST/AbsyCmd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,9 @@ int FreshAnon()
return anon++;
}

HashSet<string /*!*/> allLabels = new HashSet<string /*!*/>();
private readonly HashSet<string /*!*/> allLabels = new();

Errors /*!*/
errorHandler;
private readonly Errors /*!*/ errorHandler;

[ContractInvariantMethod]
void ObjectInvariant()
Expand Down Expand Up @@ -3445,6 +3444,8 @@ public override void Emit(TokenTextWriter stream, int level)

public class ReturnCmd : TransferCmd
{
public QKeyValue Attributes { get; set; }

public ReturnCmd(IToken /*!*/ tok)
: base(tok)
{
Expand Down Expand Up @@ -3476,6 +3477,8 @@ public class GotoCmd : TransferCmd
[Rep] public List<String> LabelNames;
[Rep] public List<Block> LabelTargets;

public QKeyValue Attributes { get; set; }

[ContractInvariantMethod]
void ObjectInvariant()
{
Expand Down
6 changes: 5 additions & 1 deletion Source/Core/AST/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ public bool IsLive(Variable v)
return liveVarsBefore.Contains(v);
}

public Block(IToken tok)
public static Block ShallowClone(Block block) {
return new Block(block.tok, block.Label, block.Cmds, block.TransferCmd);
}

public Block(IToken tok, TransferCmd cmd)
: this(tok, "", new List<Cmd>(), new ReturnCmd(tok))
{
}
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/AST/CallCmd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ protected override Cmd ComputeDesugaring(PrintOptions options)
Contract.Assert(a != null);
// These probably won't have IDs, but copy if they do.
if (callId is not null) {
a.CopyIdWithModificationsFrom(tok, req,
(a as ICarriesAttributes).CopyIdWithModificationsFrom(tok, req,
id => new TrackedCallRequiresAssumed(callId, id));
}

Expand Down Expand Up @@ -1066,7 +1066,7 @@ protected override Cmd ComputeDesugaring(PrintOptions options)
#endregion

if (callId is not null) {
assume.CopyIdWithModificationsFrom(tok, e,
(assume as ICarriesAttributes).CopyIdWithModificationsFrom(tok, e,
id => new TrackedCallEnsures(callId, id));
}

Expand Down
14 changes: 8 additions & 6 deletions Source/Core/AST/ICarriesAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,25 @@ public void AddStringAttribute(IToken tok, string name, string parameter)
Attributes = new QKeyValue(tok, name, new List<object>() {parameter}, Attributes);
}


}

public static class CarriesAttributesExtensions
{
public static void CopyIdFrom(this ICarriesAttributes dest, IToken tok, ICarriesAttributes src)
public static class CarriesAttributesExtensions {
public static void CopyIdFrom(this ICarriesAttributes destination, IToken tok, ICarriesAttributes src)
{
var id = src.FindStringAttribute("id");
if (id is not null) {
dest.AddStringAttribute(tok, "id", id);
destination.AddStringAttribute(tok, "id", id);
}
}

public static void CopyIdWithModificationsFrom(this ICarriesAttributes dest, IToken tok, ICarriesAttributes src, Func<string,TrackedNodeComponent> modifier)
public static void CopyIdWithModificationsFrom(this ICarriesAttributes destination, IToken tok,
ICarriesAttributes src, Func<string,TrackedNodeComponent> modifier)
{
var id = src.FindStringAttribute("id");
if (id is not null) {
dest.AddStringAttribute(tok, "id", modifier(id).SolverLabel);
destination.AddStringAttribute(tok, "id", modifier(id).SolverLabel);
}
}
}
8 changes: 4 additions & 4 deletions Source/Core/AST/Implementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -462,19 +462,19 @@ void BlocksWriters(TokenTextWriter stream) {
}

public void EmitImplementation(TokenTextWriter stream, int level, IEnumerable<Block> blocks,
bool showLocals) {
bool showLocals, string nameSuffix = "") {
EmitImplementation(stream, level, writer => {
foreach (var block in blocks) {
block.Emit(writer, level + 1);
}
}, showLocals);
}, showLocals, nameSuffix);
}

public void EmitImplementation(TokenTextWriter stream, int level, Action<TokenTextWriter> printBlocks, bool showLocals)
private void EmitImplementation(TokenTextWriter stream, int level, Action<TokenTextWriter> printBlocks, bool showLocals, string nameSuffix = "")
{
stream.Write(this, level, "implementation ");
EmitAttributes(stream);
stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(this.Name));
stream.Write(this, level, "{0}", TokenTextWriter.SanitizeIdentifier(Name) + nameSuffix);
EmitSignature(stream, false);
stream.WriteLine();

Expand Down
11 changes: 9 additions & 2 deletions Source/Core/AST/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -498,14 +498,17 @@ public static Graph<Implementation> BuildCallGraph(CoreOptions options, Program
return callGraph;
}

public static Graph<Block> GraphFromBlocks(List<Block> blocks, bool forward = true)
public static Graph<Block> GraphFromBlocksSubset(IReadOnlyList<Block> blocks, IReadOnlySet<Block> subset = null, bool forward = true)
{
var result = new Graph<Block>();
if (!blocks.Any())
{
return result;
}
void AddEdge(Block a, Block b) {
if (subset != null && (!subset.Contains(a) || !subset.Contains(b))) {
return;
}
Contract.Assert(a != null && b != null);
if (forward) {
result.AddEdge(a, b);
Expand All @@ -514,7 +517,7 @@ void AddEdge(Block a, Block b) {
}
}

result.AddSource(cce.NonNull(blocks[0])); // there is always at least one node in the graph
result.AddSource(blocks[0]);
foreach (var block in blocks)
{
if (block.TransferCmd is GotoCmd gtc)
Expand All @@ -525,6 +528,10 @@ void AddEdge(Block a, Block b) {
}
return result;
}

public static Graph<Block> GraphFromBlocks(IReadOnlyList<Block> blocks, bool forward = true) {
return GraphFromBlocksSubset(blocks, null, forward);
}

public static Graph<Block /*!*/> /*!*/ GraphFromImpl(Implementation impl, bool forward = true)
{
Expand Down
15 changes: 12 additions & 3 deletions Source/Core/BoogiePL.atg
Original file line number Diff line number Diff line change
Expand Up @@ -1032,14 +1032,17 @@ TransferCmd<out TransferCmd/*!*/ tc>
= (. Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd;
Token y; List<IToken>/*!*/ xs;
List<String> ss = new List<String>();
QKeyValue kv = null;
.)
( "goto" (. y = t; .)
Idents<out xs> (. foreach(IToken/*!*/ s in xs){
Contract.Assert(s != null);
ss.Add(s.val); }
tc = new GotoCmd(y, ss);
.)
| "return" (. tc = new ReturnCmd(t); .)
| "return"
{ Attribute<ref kv> }
(. tc = new ReturnCmd(t) { Attributes = kv }; .)
) ";"
.

Expand Down Expand Up @@ -1688,6 +1691,7 @@ SpecBlock<out Block/*!*/ b>
List<IToken>/*!*/ xs;
List<String> ss = new List<String>();
b = dummyBlock;
QKeyValue kv = null;
Expr/*!*/ e;
.)
Ident<out x> ":"
Expand All @@ -1706,8 +1710,13 @@ SpecBlock<out Block/*!*/ b>
ss.Add(s.val); }
b = new Block(x,x.val,cs,new GotoCmd(y,ss));
.)
| "return" Expression<out e>
(. b = new Block(x,x.val,cs,new ReturnExprCmd(t,e)); .)
| "return"
{ Attribute<ref kv> }
Expression<out e>
(. b = new Block(x,x.val,cs,new ReturnExprCmd(t,e) {
Attributes = kv
});
.)
)
";"
.
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/CoreOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace Microsoft.Boogie
public interface CoreOptions : PrintOptions {
public TextWriter OutputWriter { get; }

bool UseBaseNameForFileName { get; }

public enum TypeEncoding
{
Predicates,
Expand Down
31 changes: 31 additions & 0 deletions Source/Core/Generic/ListExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.Boogie;

public static class ListExtensions {
public static IReadOnlyList<T> Reversed<T>(this IReadOnlyList<T> list) {
return new ReversedReadOnlyList<T>(list);
}
}

class ReversedReadOnlyList<T> : IReadOnlyList<T> {
private readonly IReadOnlyList<T> inner;

public ReversedReadOnlyList(IReadOnlyList<T> inner) {
this.inner = inner;
}

public IEnumerator<T> GetEnumerator() {
return Enumerable.Range(0, inner.Count).Select(index => this[index]).GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}

public int Count => inner.Count;

public T this[int index] => inner[^(index + 1)];
}
File renamed without changes.
15 changes: 13 additions & 2 deletions Source/Core/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,7 @@ void TransferCmd(out TransferCmd/*!*/ tc) {
Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd;
Token y; List<IToken>/*!*/ xs;
List<String> ss = new List<String>();
QKeyValue kv = null;

if (la.kind == 55) {
Get();
Expand All @@ -1548,7 +1549,10 @@ void TransferCmd(out TransferCmd/*!*/ tc) {

} else if (la.kind == 56) {
Get();
tc = new ReturnCmd(t);
while (la.kind == 26) {
Attribute(ref kv);
}
tc = new ReturnCmd(t) { Attributes = kv };
} else SynErr(148);
Expect(10);
}
Expand Down Expand Up @@ -2558,6 +2562,7 @@ void SpecBlock(out Block/*!*/ b) {
List<IToken>/*!*/ xs;
List<String> ss = new List<String>();
b = dummyBlock;
QKeyValue kv = null;
Expr/*!*/ e;

Ident(out x);
Expand All @@ -2583,8 +2588,14 @@ void SpecBlock(out Block/*!*/ b) {

} else if (la.kind == 56) {
Get();
while (la.kind == 26) {
Attribute(ref kv);
}
Expression(out e);
b = new Block(x,x.val,cs,new ReturnExprCmd(t,e));
b = new Block(x,x.val,cs,new ReturnExprCmd(t,e) {
Attributes = kv
});

} else SynErr(174);
Expect(10);
}
Expand Down
15 changes: 8 additions & 7 deletions Source/Core/VariableDependenceAnalyser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -523,14 +523,14 @@ private Dictionary<Block, HashSet<Block>> ComputeGlobalControlDependences()
foreach (var impl in prog.NonInlinedImplementations())
{
var blockGraph = prog.ProcessLoops(options, impl);
localCtrlDeps[impl] = blockGraph.ControlDependence(new Block(prog.tok));
localCtrlDeps[impl] = blockGraph.ControlDependence(new Block(prog.tok, new ReturnCmd(prog.tok)));
foreach (var keyValue in localCtrlDeps[impl])
{
globalCtrlDep.Add(keyValue.Key, keyValue.Value);
}
}

var callGraph = Program.BuildCallGraph(options, prog);
Graph<Implementation> callGraph = Program.BuildCallGraph(options, prog);

// Add inter-procedural control dependence nodes based on calls
foreach (var impl in prog.NonInlinedImplementations())
Expand All @@ -548,7 +548,7 @@ private Dictionary<Block, HashSet<Block>> ComputeGlobalControlDependences()
var indirectCallees = ComputeIndirectCallees(callGraph, directCallee);
foreach (var control in GetControllingBlocks(b, localCtrlDeps[impl]))
{
foreach (var c in indirectCallees.Select(Item => Item.Blocks).SelectMany(Item => Item))
foreach (var c in indirectCallees.Select(item => item.Blocks).SelectMany(Item => Item))
{
globalCtrlDep[control].Add(c);
}
Expand All @@ -562,17 +562,18 @@ private Dictionary<Block, HashSet<Block>> ComputeGlobalControlDependences()

// Finally reverse the dependences

var result = new Dictionary<Block, HashSet<Block>>();
foreach (var keyValue in globalCtrlDep)
Dictionary<Block, HashSet<Block>> result = new Dictionary<Block, HashSet<Block>>();

foreach (var KeyValue in globalCtrlDep)
{
foreach (var v in keyValue.Value)
foreach (var v in KeyValue.Value)
{
if (!result.ContainsKey(v))
{
result[v] = new HashSet<Block>();
}

result[v].Add(keyValue.Key);
result[v].Add(KeyValue.Key);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Source/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- Target framework and package configuration -->
<PropertyGroup>
<Version>3.2.5</Version>
<Version>3.3.0</Version>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Authors>Boogie</Authors>
Expand Down
2 changes: 1 addition & 1 deletion Source/ExecutionEngine/CommandLineOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static void PassifyAllImplementations(ExecutionEngineOptions options, ProcessedP

foreach(var implementation in processedProgram.Program.Implementations) {
vcGenerator.PrepareImplementation(new ImplementationRun(implementation, options.OutputWriter),
callback, out _, out _, out _);
callback, out _, out _);
}
}

Expand Down
5 changes: 3 additions & 2 deletions Source/ExecutionEngine/ConsolePrinter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,9 @@ public virtual void ReportBplError(IToken tok, string message, bool error, TextW
message = $"{category}: {message}";
}

var s = tok != null
? $"{ExecutionEngine.GetFileNameForConsole(Options, tok.filename)}({tok.line},{tok.col}): {message}"
var s = tok != null
? string.Format("{0}({1},{2}): {3}", ExecutionEngine.GetFileNameForConsole(Options, tok.filename), tok.line,
tok.col, message)
: message;

if (error)
Expand Down
7 changes: 4 additions & 3 deletions Source/ExecutionEngine/ExecutionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -736,16 +736,15 @@ public async Task<IReadOnlyList<IVerificationTask>> GetVerificationTasks(Program
{
var writer = TextWriter.Null;
var vcGenerator = new VerificationConditionGenerator(processedProgram.Program, CheckerPool);


var run = new ImplementationRun(implementation, writer);
var collector = new VerificationResultCollector(Options);
vcGenerator.PrepareImplementation(run, collector, out _,
out var gotoCmdOrigins,
out var modelViewInfo);

ConditionGeneration.ResetPredecessors(run.Implementation.Blocks);
var splits = ManualSplitFinder.FocusAndSplit(program, Options, run, gotoCmdOrigins, vcGenerator).ToList();
var splits = ManualSplitFinder.GetParts(Options, run,
(token, blocks) => new ManualSplit(Options, () => blocks, vcGenerator, run, token)).ToList();
for (var index = 0; index < splits.Count; index++) {
var split = splits[index];
split.SplitIndex = index;
Expand Down Expand Up @@ -1310,6 +1309,8 @@ public void ProcessErrors(OutputPrinter printer,
return;
}

// When an assertion fails on multiple paths, only show an error for one of them.
errors = errors.DistinctBy(e => e.FailingAssert).ToList();
errors.Sort(new CounterexampleComparer());
foreach (Counterexample error in errors)
{
Expand Down
Loading
Loading