private List <Cmd> AbstractAssign(AssignCmd acmd) { var newcmd = new List <Cmd>(); // !KeepSimple: then map indices are given special treatment var KeepSimple = UseSimpleSlicing || (currImplementation == null) || (acmd.Lhss.Count != 1); if (acmd.Lhss.Count != 1) { EncounteredParallelAssignment = true; } var newLhss = new List <AssignLhs>(); var newRhss = new List <Expr>(); var varsToHavoc = new HashSet <Variable>(); for (int i = 0; i < acmd.Lhss.Count; i++) { AssignLhs lhs = acmd.Lhss[i]; Expr rhs = acmd.Rhss[i]; //IdentifierExpr assignedVar = getAssignedVariable(lhs); IdentifierExpr assignedVar = lhs.DeepAssignedIdentifier; if (isTrackedVariable(assignedVar.Decl)) { if (lhs is MapAssignLhs && !indicesAreTracked((MapAssignLhs)lhs)) { // convert to assignedVar := * varsToHavoc.Add(assignedVar.Decl); } else if (!isTracked(rhs)) { // Convert to lhs := * if (KeepSimple || lhs is SimpleAssignLhs) { varsToHavoc.Add(assignedVar.Decl); } else { // convert to "havoc lhs" as follows: // havoc dummy; lhs := dummy; // This is done when lhs is Mem[x]. We're not // allowed to say "havoc Mem[x]". // We should be doing this only when we can add new // local variables Debug.Assert(currImplementation != null); // Get new local variable dummy LocalVariable dummy = getNewLocal(lhs.Type, currImplementation); // havoc dummy newcmd.Add(BoogieAstFactory.MkHavocVar(dummy)); // lhs := dummy newLhss.Add(lhs); newRhss.Add(Expr.Ident(dummy)); } } else { // It is possible to come here because a variable may be untracked in this scope, // yet tracked globally because it is on the lhs newLhss.Add(lhs); newRhss.Add(rhs); } } } if (newLhss.Count != 0) { newcmd.Add(new AssignCmd(Token.NoToken, newLhss, newRhss)); } if (varsToHavoc.Count != 0) { var ieseq = new List <IdentifierExpr>(); varsToHavoc.Iter(v => ieseq.Add(Expr.Ident(v))); newcmd.Add(new HavocCmd(Token.NoToken, ieseq)); } return(newcmd); }