public override List <Cmd> CreateUpdatesToRefinementVars(bool isMarkedCall) { var cmds = new List <Cmd>(); var pcOkUpdateLHS = new List <IdentifierExpr> { Expr.Ident(pc), Expr.Ident(ok) }; if (isMarkedCall) { // assert !pc; // pc, ok := true, true; cmds.Add(CmdHelper.AssertCmd(tok, Expr.Not(Expr.Ident(pc)), $"Layer-{layerNum + 1} state modified before marked call")); var pcOkUpdateRHS = new List <Expr> { Expr.True, Expr.True }; cmds.Add(CmdHelper.AssignCmd(pcOkUpdateLHS, pcOkUpdateRHS)); } else { // pc, ok := g_old == g ==> pc, transitionRelation(i, g_old, o, g) || (o_old == o && ok); var pcOkUpdateRHS = new List <Expr> { Expr.Imp(OldEqualityExprForGlobals(), Expr.Ident(pc)), Expr.Or(transitionRelation, Expr.And(OldEqualityExprForOutputs(), Expr.Ident(ok))), }; cmds.Add(CmdHelper.AssignCmd(pcOkUpdateLHS, pcOkUpdateRHS)); } CivlUtil.ResolveAndTypecheck(cmds); return(cmds); }
private AssertCmd GetCheck(Expr expr) { expr.Typecheck(new TypecheckingContext(null)); return(CmdHelper.AssertCmd( inputAction.proc.tok, expr, $"IS {checkName} of {inputAction.proc.Name} failed")); }
private void CreateGatePreservationChecker(AtomicAction first, AtomicAction second) { if (!first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Any()) { return; } if (!gatePreservationCheckerCache.Add(Tuple.Create(first, second))) { return; } HashSet <Variable> frame = new HashSet <Variable>(); frame.UnionWith(first.gateUsedGlobalVars); frame.UnionWith(second.gateUsedGlobalVars); frame.UnionWith(second.actionUsedGlobalVars); var linearTypeChecker = civlTypeChecker.linearTypeChecker; List <Requires> requires = new List <Requires> { DisjointnessRequires( first.firstImpl.InParams.Union(second.secondImpl.InParams) .Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT), frame) }; foreach (AssertCmd assertCmd in first.firstGate.Union(second.secondGate)) { requires.Add(new Requires(false, assertCmd.Expr)); } string checkerName = $"GatePreservationChecker_{first.proc.Name}_{second.proc.Name}"; List <Variable> inputs = Enumerable.Union(first.firstImpl.InParams, second.secondImpl.InParams).ToList(); List <Variable> outputs = Enumerable.Union(first.firstImpl.OutParams, second.secondImpl.OutParams).ToList(); List <Cmd> cmds = new List <Cmd> { ActionCallCmd(second, second.secondImpl) }; IEnumerable <Expr> linearityAssumes = linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.InParams.Union(second.secondImpl.OutParams) .Union(frame)); foreach (AssertCmd assertCmd in first.firstGate) { cmds.Add( CmdHelper.AssertCmd( assertCmd.tok, Expr.Imp(Expr.And(linearityAssumes), assertCmd.Expr), $"Gate of {first.proc.Name} not preserved by {second.proc.Name}" ) ); } AddChecker(checkerName, inputs, outputs, new List <Variable>(), requires, cmds); }
public static void AddCheckers(CivlTypeChecker civlTypeChecker) { foreach (var action in civlTypeChecker.AllAtomicActions.Where(a => a.HasPendingAsyncs)) { var requires = action.gate.Select(g => new Requires(false, g.Expr)).ToList(); var PAs = Expr.Ident(action.impl.OutParams.Last(p => p.TypedIdent.Type.Equals(civlTypeChecker.pendingAsyncMultisetType))); var paBound = civlTypeChecker.BoundVariable("pa", civlTypeChecker.pendingAsyncType); var pa = Expr.Ident(paBound); var nonnegativeExpr = ExprHelper.ForallExpr(new List <Variable> { paBound }, Expr.Ge(Expr.Select(PAs, pa), Expr.Literal(0))); var correctTypeExpr = ExprHelper.ForallExpr(new List <Variable> { paBound }, Expr.Imp( Expr.Gt(Expr.Select(PAs, pa), Expr.Literal(0)), Expr.Or(action.pendingAsyncs.Select(a => ExprHelper.FunctionCall(a.pendingAsyncCtor.membership, pa))))); CivlUtil.ResolveAndTypecheck(nonnegativeExpr); CivlUtil.ResolveAndTypecheck(correctTypeExpr); var cmds = new List <Cmd> { CmdHelper.CallCmd( action.proc, action.impl.InParams.Select(Expr.Ident).ToList <Expr>(), action.impl.OutParams.Select(Expr.Ident).ToList()), CmdHelper.AssertCmd( action.proc.tok, nonnegativeExpr, $"Action {action.proc.Name} might create negative pending asyncs"), CmdHelper.AssertCmd( action.proc.tok, correctTypeExpr, $"Action {action.proc.Name} might create undeclared pending asyncs") }; var blocks = new List <Block>() { BlockHelper.Block("init", cmds) }; var proc = DeclHelper.Procedure(civlTypeChecker.AddNamePrefix($"PendingAsyncChecker_{action.proc.Name}"), action.impl.InParams, action.impl.OutParams, requires, action.proc.Modifies, new List <Ensures>()); var impl = DeclHelper.Implementation(proc, proc.InParams, proc.OutParams, new List <Variable>(), blocks); civlTypeChecker.program.AddTopLevelDeclaration(proc); civlTypeChecker.program.AddTopLevelDeclaration(impl); } }
public override List <Cmd> CreateReturnAssertCmds() { AssertCmd assertCmd = CmdHelper.AssertCmd( tok, Expr.Ident(ok), "On some path no yield-to-yield fragment matched the refined atomic action"); return(new List <Cmd> { assertCmd }); }
public Tuple <Procedure, Implementation> GenerateChoiceChecker() { this.checkName = "choice"; var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList(); List <Cmd> cmds = new List <Cmd>(); cmds.Add(GetCallCmd(invariantAction)); cmds.Add(CmdHelper.AssumeCmd(ExistsElimPendingAsyncExpr)); cmds.Add(CmdHelper.AssertCmd( invariantAction.proc.tok, ElimPendingAsyncExpr(choice), $"Failed to validate choice in IS of {inputAction.proc.Name}")); return(GetCheckerTuple(requires, new List <Variable>(), cmds)); }
private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(CivlTypeChecker civlTypeChecker, AtomicAction action, AtomicAction abs) { var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList(); // TODO: check frame computation var frame = new HashSet <Variable>( action.modifiedGlobalVars .Union(action.gateUsedGlobalVars) .Union(abs.modifiedGlobalVars) .Union(abs.gateUsedGlobalVars)); var subst = InductiveSequentialization.GetSubstitution(action, abs); List <Cmd> cmds = InductiveSequentialization.GetGateAsserts(action, subst, $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>(); cmds.Add( CmdHelper.CallCmd( action.proc, abs.impl.InParams, abs.impl.OutParams )); cmds.Add( CmdHelper.AssertCmd( abs.proc.tok, TransitionRelationComputation.Refinement(civlTypeChecker, abs, frame), $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}" )); var blocks = new List <Block> { BlockHelper.Block("init", cmds) }; var proc = DeclHelper.Procedure( civlTypeChecker.AddNamePrefix($"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}"), abs.impl.InParams, abs.impl.OutParams, requires, action.proc.Modifies, new List <Ensures>()); var impl = DeclHelper.Implementation( proc, proc.InParams, proc.OutParams, new List <Variable>(), blocks); return(Tuple.Create(proc, impl)); }
public Tuple <Procedure, Implementation> GenerateConclusionChecker() { this.checkName = "conclusion"; var subst = GetSubstitution(outputAction, invariantAction); var requires = outputAction.gate.Select(g => new Requires(false, Substituter.Apply(subst, g.Expr))).ToList(); List <Cmd> cmds = GetGateAsserts(invariantAction, null).ToList <Cmd>(); cmds.Add(GetCallCmd(invariantAction)); cmds.Add(CmdHelper.AssumeCmd(PendingAsyncsEliminatedExpr)); cmds.Add(GetCheck(Substituter.Apply(subst, GetTransitionRelation(outputAction)))); if (!outputAction.HasPendingAsyncs) { cmds.Add(CmdHelper.AssertCmd( inputAction.proc.tok, NoPendingAsyncs, $"IS leaves pending asyncs not summarized by ${outputAction.proc.Name}")); } return(GetCheckerTuple(requires, new List <Variable>(), cmds)); }
public override List <Cmd> CreateUnchangedAssertCmds() { AssertCmd globalsAssertCmd = CmdHelper.AssertCmd( tok, Expr.And(this.oldGlobalMap.Select(kvPair => Expr.Eq(Expr.Ident(kvPair.Key), Expr.Ident(kvPair.Value)))), $"A yield-to-yield fragment illegally modifies layer-{layerNum + 1} globals"); CivlUtil.ResolveAndTypecheck(globalsAssertCmd); // assert pc ==> o_old == o; AssertCmd outputsAssertCmd = CmdHelper.AssertCmd( tok, Expr.Imp(Expr.Ident(pc), OldEqualityExprForOutputs()), $"A yield-to-yield fragment illegally modifies layer-{layerNum + 1} outputs"); CivlUtil.ResolveAndTypecheck(outputsAssertCmd); return(new List <Cmd> { globalsAssertCmd, outputsAssertCmd }); }
public override List <Cmd> CreateAssertCmds() { // assert pc || g_old == g || transitionRelation(i, g_old, o, g); var skipOrTransitionRelationAssertCmd = CmdHelper.AssertCmd( tok, Expr.Or(Expr.Ident(pc), Expr.Or(OldEqualityExprForGlobals(), transitionRelation)), $"A yield-to-yield fragment modifies layer-{layerNum + 1} state in a way that does not match the refined atomic action"); CivlUtil.ResolveAndTypecheck(skipOrTransitionRelationAssertCmd); // assert pc ==> g_old == g && o_old == o; AssertCmd skipAssertCmd = CmdHelper.AssertCmd( tok, Expr.Imp(Expr.Ident(pc), Expr.And(OldEqualityExprForGlobals(), OldEqualityExprForOutputs())), $"A yield-to-yield fragment modifies layer-{layerNum + 1} state subsequent to a yield-to-yield fragment that already modified layer-{layerNum + 1} state"); CivlUtil.ResolveAndTypecheck(skipAssertCmd); return(new List <Cmd> { skipOrTransitionRelationAssertCmd, skipAssertCmd }); }
private void CreateCooperationChecker(Action action) { if (!action.HasAssumeCmd) { return; } string checkerName = $"CooperationChecker_{action.proc.Name}"; Implementation impl = action.impl; HashSet <Variable> frame = new HashSet <Variable>(); frame.UnionWith(action.gateUsedGlobalVars); frame.UnionWith(action.actionUsedGlobalVars); List <Requires> requires = new List <Requires> { DisjointnessRequires(impl.InParams.Where(v => civlTypeChecker.linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT), frame) }; foreach (AssertCmd assertCmd in action.gate) { requires.Add(new Requires(false, assertCmd.Expr)); } AssertCmd cooperationCheck = CmdHelper.AssertCmd( action.proc.tok, TransitionRelationComputation.Cooperation(civlTypeChecker, action, frame), $"Cooperation check for {action.proc.Name} failed"); AddChecker(checkerName, new List <Variable>(impl.InParams), new List <Variable>(), new List <Variable>(), requires, new List <Cmd> { cooperationCheck }); }
private void CreateCommutativityChecker(AtomicAction first, AtomicAction second) { if (first == second && first.firstImpl.InParams.Count == 0 && first.firstImpl.OutParams.Count == 0) { return; } if (first.TriviallyCommutesWith(second)) { return; } if (!commutativityCheckerCache.Add(Tuple.Create(first, second))) { return; } string checkerName = $"CommutativityChecker_{first.proc.Name}_{second.proc.Name}"; HashSet <Variable> frame = new HashSet <Variable>(); frame.UnionWith(first.gateUsedGlobalVars); frame.UnionWith(first.actionUsedGlobalVars); frame.UnionWith(second.gateUsedGlobalVars); frame.UnionWith(second.actionUsedGlobalVars); var linearTypeChecker = civlTypeChecker.linearTypeChecker; List <Requires> requires = new List <Requires> { DisjointnessRequires( first.firstImpl.InParams.Union(second.secondImpl.InParams) .Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT), frame) }; foreach (AssertCmd assertCmd in Enumerable.Union(first.firstGate, second.secondGate)) { requires.Add(new Requires(false, assertCmd.Expr)); } var witnesses = civlTypeChecker.commutativityHints.GetWitnesses(first, second); var transitionRelation = TransitionRelationComputation.Commutativity(civlTypeChecker, second, first, frame, witnesses); var secondInParamsFiltered = second.secondImpl.InParams.Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_IN); IEnumerable <Expr> linearityAssumes = Enumerable.Union( linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.OutParams.Union(secondInParamsFiltered) .Union(frame)), linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.OutParams.Union(second.secondImpl.OutParams) .Union(frame))); // TODO: add further disjointness expressions? AssertCmd commutativityCheck = CmdHelper.AssertCmd( first.proc.tok, Expr.Imp(Expr.And(linearityAssumes), transitionRelation), $"Commutativity check between {first.proc.Name} and {second.proc.Name} failed"); List <Cmd> cmds = new List <Cmd> { ActionCallCmd(first, first.firstImpl), ActionCallCmd(second, second.secondImpl) }; foreach (var lemma in civlTypeChecker.commutativityHints.GetLemmas(first, second)) { cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(lemma.function, lemma.args.ToArray()))); } cmds.Add(commutativityCheck); List <Variable> inputs = Enumerable.Union(first.firstImpl.InParams, second.secondImpl.InParams).ToList(); List <Variable> outputs = Enumerable.Union(first.firstImpl.OutParams, second.secondImpl.OutParams).ToList(); AddChecker(checkerName, inputs, outputs, new List <Variable>(), requires, cmds); }