Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
e35cd50
Initial commit for UCLID5 backend. Mostly type definitions for now.
FedericoAureliano Apr 21, 2024
6c0c39b
Start encoding of handlers and statements. Need to encode expressions.
FedericoAureliano Apr 22, 2024
06808ad
small update to assignment handling and generate comments to see what…
FedericoAureliano Apr 22, 2024
b81933b
add next block
FedericoAureliano May 1, 2024
3222cb6
support more statements and expressions
FedericoAureliano May 2, 2024
3137f00
refactor before adding helper functions to shorten explicit strings
FedericoAureliano May 6, 2024
af110ea
use more macros so that updates are consistent. Also, use local varia…
FedericoAureliano May 7, 2024
a94c241
WIP: UCLID reserved words, like input, need to be taken care of when …
FedericoAureliano May 9, 2024
0fccb6b
switch from enums for state to datatypes
FedericoAureliano May 9, 2024
6c6328b
fix bug in skipping handlers; use .States consistently. WIP: need to …
FedericoAureliano May 9, 2024
64f4609
Update UCLID5 backend: avoid keywords through prefix scheme
FedericoAureliano May 23, 2024
258fc60
add support for maps
FedericoAureliano May 23, 2024
89af064
Functions are procedures; implement call site; need to generate proce…
FedericoAureliano May 30, 2024
f6e79da
add support for helper function bodies as UCLID procedures. Always ca…
FedericoAureliano May 31, 2024
1d606f2
add simple chain replication and update compiler to handle it
FedericoAureliano Jun 7, 2024
91fc1b5
add helper for setting field defaults for maps and sets; init fields …
FedericoAureliano Jun 7, 2024
b7b2f75
fix bug in precodnition for event handlers
FedericoAureliano Jun 7, 2024
98b6878
add happy path chain replication
FedericoAureliano Jun 11, 2024
687ebd4
add ucl files
FedericoAureliano Jun 11, 2024
03372e0
checkpoint chain replication
FedericoAureliano Jun 17, 2024
763288c
add support for foreach statements, default expressions, etc, before …
FedericoAureliano Jun 21, 2024
806048c
add goto types
FedericoAureliano Jun 24, 2024
255d708
add label type
FedericoAureliano Jun 24, 2024
71aa29b
gotos should carry target. Need to redo procedures and next block to …
FedericoAureliano Jun 24, 2024
196ab9f
WIP: rewrite UCLID5 backend to use labels and not have implicit ignor…
FedericoAureliano Jun 27, 2024
0fe5229
Finish foundation of new encoding
FedericoAureliano Jun 28, 2024
d13bd38
inline deref function
FedericoAureliano Jul 1, 2024
6aac546
WIP: add support for spec machines. Now constructing listener map, ne…
FedericoAureliano Jul 2, 2024
1a2df28
add spec procedure calls after evry send
FedericoAureliano Jul 2, 2024
0a55df7
WIP: add invariant to parser
FedericoAureliano Jul 3, 2024
4710f7a
add support for invariants at the P level
FedericoAureliano Jul 5, 2024
273228d
add support for quantifier expressions
FedericoAureliano Jul 5, 2024
f23ab73
add support for quantifying over machines
FedericoAureliano Jul 5, 2024
c017236
fix bugs in permission type quantification
FedericoAureliano Jul 5, 2024
6156b00
add support for pure, a keyword for specification functions. Need to …
FedericoAureliano Jul 5, 2024
37da5ae
add enough proof syntax to prove that clients in chain rep don't rece…
FedericoAureliano Jul 10, 2024
2558d05
add 9, fix compiler bug for empty events, start proof
FedericoAureliano Jul 12, 2024
866417d
add axiom keyword
FedericoAureliano Jul 12, 2024
c8ef7dd
add support for testing state
FedericoAureliano Jul 12, 2024
9321e53
incorrect proof. Need to find contradiction
FedericoAureliano Jul 14, 2024
96635be
make sure to verify all procedurs
FedericoAureliano Jul 14, 2024
2bb426e
add support for quantifying over and selecting from specific event kinds
FedericoAureliano Jul 14, 2024
14b5ff7
add partial 2pc proof. Need to add syntax for talking about state delay
FedericoAureliano Jul 14, 2024
9cda339
add compiler pass to uclid backend
FedericoAureliano Jul 15, 2024
5434886
add difference constraints
FedericoAureliano Jul 16, 2024
050d221
full 2pc proof
FedericoAureliano Jul 16, 2024
f8b329f
deal with final proof obligation of 2pc
FedericoAureliano Jul 16, 2024
4600bf2
add simple chain replication verification, add spec machine field acc…
FedericoAureliano Jul 19, 2024
3f1de82
add unique identifier to actions and automatically prove that it is a…
FedericoAureliano Jul 19, 2024
c51ea76
add sent keyword
FedericoAureliano Jul 20, 2024
eb916a7
remove stale examples. Will add back later when updated.
FedericoAureliano Jul 20, 2024
0492a75
rename tutorial
FedericoAureliano Jul 29, 2024
7416626
add support for limited map nesting; start adding multi round 2pc
FedericoAureliano Jul 29, 2024
0408aa2
start adding support for choose (placeholder); add support for assume
FedericoAureliano Jul 29, 2024
74731b6
update 2pc rounds with assumption; add ring leader election that need…
FedericoAureliano Jul 29, 2024
e92454b
add limited support for choose expressions
FedericoAureliano Jul 30, 2024
dbf1089
add support for pure functions with bodies
FedericoAureliano Jul 30, 2024
85ec417
better verification feedback for users
FedericoAureliano Jul 30, 2024
efe7eb5
add timeout for UCLID5 backend
FedericoAureliano Jul 31, 2024
a8f3198
allow for specific events in diff loop invaraints
FedericoAureliano Jul 31, 2024
c5b86fd
start generalizing 2pc with rounds
FedericoAureliano Jul 31, 2024
19523ba
finish 2pc rounds; fix bug with negative timeout value
FedericoAureliano Jul 31, 2024
d5cc1d7
reorganize verification tutorial
FedericoAureliano Aug 1, 2024
61e7d75
add feedback for failing to prove assertions and update 2pc kv exampl…
FedericoAureliano Aug 1, 2024
e0a3e97
add kv version of 2pc that has a consistency monitor
FedericoAureliano Aug 2, 2024
956f2b8
make users init fields to default values
FedericoAureliano Aug 5, 2024
6ef2a5d
fix bug when spec machine handlers don't take arguments
FedericoAureliano Aug 5, 2024
c942bef
add support for return statements (although we are not actually exiti…
FedericoAureliano Aug 5, 2024
77b873c
fix bug in global procedure bindings; inline procedures unless they d…
FedericoAureliano Aug 6, 2024
54068a7
handle empty payloads for spec handlers
FedericoAureliano Aug 7, 2024
6c28c75
add parens around state check to avoid binding issues; update 2pc-key…
FedericoAureliano Aug 9, 2024
7d6b76d
[fix] canonicalize container type before checking for codegen
AD1024 Aug 9, 2024
0610a6d
add 'handles-all' flag that can be turned off to avoid checking that …
FedericoAureliano Aug 10, 2024
c2008b0
add support for iterating over maps with the keys expression
FedericoAureliano Aug 10, 2024
1332d96
more missing parens
FedericoAureliano Aug 11, 2024
91cd64e
add check-only argument and change no-event-handler-checks to a flag
FedericoAureliano Aug 11, 2024
3382cb7
fix bugs in new command line options
FedericoAureliano Aug 11, 2024
2406602
no need to run any handlers in next block. Fix condition for check on…
FedericoAureliano Aug 11, 2024
d5667a1
don't forget to check the base case!
FedericoAureliano Aug 12, 2024
fb3eef4
relax type checking on pure functions
FedericoAureliano Aug 12, 2024
29aacdb
do not init local variables to default values
FedericoAureliano Aug 13, 2024
a725cb6
add missing local variable declarations for global procedures
FedericoAureliano Aug 14, 2024
334b856
Merge branch 'experimental/pverifier' into master
ankushdesai Aug 21, 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
Prev Previous commit
Next Next commit
add support for foreach statements, default expressions, etc, before …
…moving to new encoding
  • Loading branch information
FedericoAureliano committed Jun 21, 2024
commit 763288c9cf68f7d2133b25e7cf0ba7ffa0a6aeee
157 changes: 139 additions & 18 deletions 157 Src/PCompiler/CompilerCore/Backend/Uclid5/Uclid5CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class Uclid5CodeGenerator : ICodeGenerator
private CompiledFile _src;

private HashSet<PLanguageType> _optionsToDeclare;
private HashSet<SetType> _setCheckersToDeclare;

private static string BuiltinPrefix => "UPVerifier_";
private static string UserPrefix => "User_";
Expand Down Expand Up @@ -50,6 +51,7 @@ public IEnumerable<CompiledFile> GenerateCode(ICompilerConfiguration job, Scope
_ctx = new CompilationContext(job);
_src = new CompiledFile(_ctx.FileName);
_optionsToDeclare = [];
_setCheckersToDeclare = new HashSet<SetType>();
GenerateMain(globalScope);
return new List<CompiledFile> { _src };
}
Expand All @@ -68,11 +70,13 @@ private void GenerateMain(Scope globalScope)
GenerateMachineDefs(machines);
GenerateBuiltInVarDecls();
GenerateInitBlock();
GenerateHelperProcedures(globalScope.AllDecls.OfType<Function>());
GenerateGlobalProcedures(globalScope.AllDecls.OfType<Function>());
GenerateMachineProcedures(machines);
GenerateEntryProcedures(machines);
GenerateHandlerProcedures(machines);
GenerateNextBlock(machines);
GenerateOptionTypes();
GenerateCheckerVars();
GenerateControlBlock(machines);

// close the main module
Expand All @@ -88,6 +92,11 @@ private void GenerateBuiltInTypeDefs()
EmitLine("\n");
}

private string GetLocation(IPAST node)
{
return _ctx.LocationResolver.GetLocation(node.SourceLocation).ToString();
}

private static string GetUserName(string r)
{
return $"{UserPrefix}{r}";
Expand Down Expand Up @@ -277,20 +286,26 @@ private string InStartPredicate(Machine m, string mname)
return $"{mname}.{GetState(m)} == {GetMachineName(m.Name)}_{GetStartState(m)}()";
}

private string DefaultValue(PLanguageType ty)
{
return ty switch
{
MapType mapType =>
$"const({ConstructOptionNone(TypeToString(mapType.ValueType))}, {TypeToString(mapType)})",
SetType setType => $"const(false, {TypeToString(setType)})",
_ => throw new ArgumentOutOfRangeException($"{ty} ({ty.GetType()})")
};
}

private string InDefaultPredicate(Machine m, string mname)
{
var cond = $"{mname}.{GetState(m)} == {GetMachineName(m.Name)}_{GetStartState(m)}()";
foreach (var f in m.Fields)
{
switch (f.Type)
// TODO; defaults for all types?
if (f.Type.TypeKind == TypeKind.Map || f.Type.TypeKind == TypeKind.Set)
{
case MapType mapType:
cond += $" && {mname}.{GetField(m, f)} == const({ConstructOptionNone(TypeToString(mapType.ValueType))}, {TypeToString(mapType)})";
break;
case SetType setType:
cond += $" && {mname}.{GetField(m, f)} == const(false, {TypeToString(setType)})";
break;
// TODO; defaults for all types?
cond += $" && {mname}.{GetField(m, f)} == {DefaultValue(f.Type)}";
}
}
return cond;
Expand Down Expand Up @@ -385,7 +400,36 @@ private void GenerateInitBlock()
EmitLine("\n");
}

private void GenerateHelperProcedures(IEnumerable<Function> functions)
private void GenerateMachineProcedures(List<Machine> ms)
{
foreach (var m in ms)
{
foreach (var f in m.Methods)
{
if (f.IsAnon)
{
continue;
}
var ps = f.Signature.Parameters.Select(p => $"{p.Name}: {TypeToString(p.Type)}").Prepend($"{This}: {RefT}");
EmitLine($"procedure [noinline] {f.Name}({string.Join(", ", ps)})");
EmitLine($"\trequires {IsMachineInstance(GetMachine(This), m)};");
EmitLine(
$"\tensures (forall (r1: {RefT}) :: {This} != r1 ==> old({Machines})[r1] == {GetMachine("r1")});");
if (!f.Signature.ReturnType.IsSameTypeAs(PrimitiveType.Null))
{
EmitLine($"\treturns ({ReturnVar}: {TypeToString(f.Signature.ReturnType)})");
}
EmitLine("{");
GenerateGenericHandlerVars(m, f);
GenerateStmt(f.Body);
GenerateGenericHandlerPost(m);
EmitLine("}\n");
}
EmitLine("\n");
}
}

private void GenerateGlobalProcedures(IEnumerable<Function> functions)
{
foreach (var f in functions)
{
Expand All @@ -404,8 +448,6 @@ private void GenerateHelperProcedures(IEnumerable<Function> functions)

private void GenerateGenericHandlerSpec(Machine m, State s)
{
EmitLine($"\tmodifies {Machines};");
EmitLine($"\tmodifies {Buffer};");
EmitLine($"\trequires {IsMachineInstance(GetMachine(This), m)};");
EmitLine($"\trequires {IsMachineStateInstance(GetMachine(This), m, s)};");
EmitLine(
Expand Down Expand Up @@ -583,7 +625,7 @@ private void GenerateStmt(IPStmt stmt)
return;
}
throw new NotSupportedException(
$"Not supported assignment expression: {cstmt} ({cstmt.SourceLocation})");
$"Not supported assignment expression with call: {cstmt.Location} = {cstmt.Value} ({GetLocation(cstmt)})");
case AssignStmt astmt:
switch (astmt.Location)
{
Expand All @@ -596,10 +638,20 @@ private void GenerateStmt(IPStmt stmt)
var valueType = TypeToString(((MapType)max.MapExpr.Type).ValueType);
EmitLine($"{map} = {map}[{index} -> {ConstructOptionSome(valueType, ExprToString(astmt.Value))}];");
return;
case NamedTupleAccessExpr {SubExpr: VariableAccessExpr} tax:
var subExpr = ExprToString(tax.SubExpr);
var entry = tax.Entry.Name;
var field = tax.FieldName;
var fields = ((NamedTupleType)((TypeDefType)tax.SubExpr.Type).TypeDefDecl.Type).Fields;
var rhs = ExprToString(astmt.Value);
var build = string.Join(", ", fields.Select(f => f.Name == entry ? $"{entry} := {rhs}" : $"{f.Name} := {subExpr}.{f.Name}"));
EmitLine($"// subExpr: {subExpr}; entry {entry}; field: {field}");
EmitLine($"{subExpr} = const_record({build});");
return;
}

throw new NotSupportedException(
$"Not supported assignment expression: {astmt} ({astmt.SourceLocation})");
$"Not supported assignment expression: {astmt.Location} = {astmt.Value} ({GetLocation(astmt)})");
case IfStmt ifstmt:
var cond = (ifstmt.Condition) switch
{
Expand Down Expand Up @@ -634,22 +686,80 @@ private void GenerateStmt(IPStmt stmt)
EmitLine($"call {fapp.Function.Name}({string.Join(", ", fapp.ArgsList.Select(ExprToString).Prepend(This))});");
return;
case AddStmt astmt:
var set = ExprToString(astmt.Variable);
var key = ExprToString(astmt.Value);
EmitLine($"{set} = {set}[{key} -> true];");
var aset = ExprToString(astmt.Variable);
var akey = ExprToString(astmt.Value);
EmitLine($"{aset} = {aset}[{akey} -> true];");
return;
case RemoveStmt rstmt:
var rset = ExprToString(rstmt.Variable);
var rkey = ExprToString(rstmt.Value);

switch (rstmt.Variable.Type)
{
case MapType mapType:
EmitLine($"{rset} = {rset}[{rkey} -> {ConstructOptionNone(TypeToString(mapType.ValueType))}];");
return;
case SetType setType:
EmitLine($"{rset} = {rset}[{rkey} -> false];");
return;
default:
throw new NotSupportedException($"Only support remove statemetns for sets and maps, got {rstmt.Variable.Type}");
}
case InsertStmt istmt:
var imap = ExprToString(istmt.Variable);
var idx = ExprToString(istmt.Index);
var value = ConstructOptionSome(TypeToString(istmt.Value.Type), ExprToString(istmt.Value));
EmitLine($"{imap} = {imap}[{idx} -> {value}];");
return;
case WhileStmt wstmt:
var wcond = ExprToString(wstmt.Condition);
EmitLine($"while ({wcond}) {{");
GenerateStmt(wstmt.Body);
EmitLine("}");
return;
case ForeachStmt fstmt:
var item = GetLocalName(fstmt.Item.Name);
var checker = GetCheckerName(fstmt.IterCollection.Type);
var collection = ExprToString(fstmt.IterCollection);

switch (fstmt.IterCollection.Type)
{
case SetType setType:
// set the checker to default
EmitLine($"{checker} = {DefaultValue(setType)};");
// remember to declare it later
_setCheckersToDeclare.Add(setType);
// havoc the item
EmitLine($"havoc {item};");
EmitLine($"while ({checker} != {collection}) {{");
// assume that the item is in the set but hasn't been visited
EmitLine($"assume ({collection}[{item}] && !{checker}[{item}]);");
// the body of the loop
GenerateStmt(fstmt.Body);
// update the checker
EmitLine($"{checker} = {checker}[{item} -> true];");
// havoc the item
EmitLine($"havoc {item};");
EmitLine("}");
return;
default:
throw new NotSupportedException($"Foreach over non-sets is not supported yet: {fstmt} ({GetLocation(fstmt)}");
}
case null:
return;
}
throw new NotSupportedException($"Not supported statement: {stmt} ({stmt.SourceLocation})");
throw new NotSupportedException($"Not supported statement: {stmt} ({GetLocation(stmt)})");
}

private string GetCheckerName(PLanguageType ty)
{
return ty switch
{
MapType mapType => $"{BuiltinPrefix}Checker_{TypeToString(mapType.KeyType)}",
SetType setType => $"{BuiltinPrefix}Checker_{TypeToString(setType.ElementType)}",
_ => throw new ArgumentOutOfRangeException(nameof(ty))
};
}

private string TypeToString(PLanguageType t)
{
Expand Down Expand Up @@ -711,6 +821,7 @@ private string ExprToString(IPExpr expr)
SetType _ => $"{ExprToString(cexp.Collection)}[{ExprToString(cexp.Item)}]",
_ => throw new NotSupportedException($"Not supported expr: {expr} of {cexp.Type.OriginalRepresentation}")
},
DefaultExpr dexp => DefaultValue(dexp.Type),
_ => throw new NotSupportedException($"Not supported expr: {expr}")
// _ => $"NotHandledExpr({expr})"
};
Expand Down Expand Up @@ -769,6 +880,16 @@ private void GenerateOptionTypes()
EmitLine("\n");
}

private void GenerateCheckerVars()
{
foreach (var ptype in _setCheckersToDeclare)
{
var name = GetCheckerName(ptype);
EmitLine($"var {name}: {TypeToString(ptype)};");
}
EmitLine("\n");
}

private void GenerateControlBlock(IEnumerable<Machine> ms)
{
var machines = ms.ToList();
Expand Down
43 changes: 14 additions & 29 deletions 43 Tutorial/6_TwoPhaseCommitVerification/PSrc/Client.p
Original file line number Diff line number Diff line change
@@ -1,46 +1,31 @@
machine Client {
var coordinator: Coordinator;
var currTransaction : tTrans;
var N: int;
var id: int;
var currTransaction: tTrans;
var count: int;

start state Init {
entry (payload : (coordinator: Coordinator, n : int, id: int)) {
entry (payload : (coordinator: Coordinator, count: int)) {
coordinator = payload.coordinator;
N = payload.n;
id = payload.id;
count = payload.count;
goto SendWriteTransaction;
}
}

state SendWriteTransaction {
entry {
currTransaction = ChooseRandomTransaction(id * 100 + N /* hack for creating unique transaction id*/);
send coordinator, eWriteTransReq, (client = this, trans = currTransaction);
}
on eWriteTransResp goto ConfirmTransaction;
}

state ConfirmTransaction {
entry (writeResp: tWriteTransResp) {
if(writeResp.status == SUCCESS)
{
send coordinator, eReadTransReq, (client= this, key = currTransaction.key);
receive {
case eReadTransResp: (readResp: tReadTransResp) {
assert readResp.key == currTransaction.key && readResp.val == currTransaction.val,
format ("Record read is not same as what was written by the client:: read - {0}, written - {1}",
readResp.val, currTransaction.val);
}
}
}
if(N > 0)
{
N = N - 1;
if ($) {
currTransaction = CreateRandomTransaction();
// subexpr . entry = rhs
currTransaction.transId = (client = this, count = count);
send coordinator, eWriteTransReq, (client = this, trans = currTransaction);
} else {
goto SendWriteTransaction;
}
}
on eWriteTransResp do (writeResp: tWriteTransResp) {
goto SendWriteTransaction;
}
}
}

fun ChooseRandomTransaction(uniqueId: int): tTrans;
fun CreateRandomTransaction(): tTrans;
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.