in ironclad-apps/tools/DafnySpec/Compile.cs [908:1119]
public virtual void AddResolvedGhostStatement(Statement stmt, Attributes attrs)
{
BlockStmt block = stmt as BlockStmt;
IfStmt ifStmt = stmt as IfStmt;
AssertStmt assertStmt = stmt as AssertStmt;
AssignStmt assignStmt = stmt as AssignStmt;
CallStmt callStmt = stmt as CallStmt;
VarDeclStmt varDecl = stmt as VarDeclStmt;
CalcStmt calcStmt = stmt as CalcStmt;
ForallStmt forallStmt = stmt as ForallStmt;
AssignSuchThatStmt existsStmt = stmt as AssignSuchThatStmt;
if (block != null)
{
var oldRenamer = PushRename();
block.Body.ForEach(s => AddGhostStatement(s, attrs));
PopRename(oldRenamer);
}
else if (varDecl != null)
{
foreach (var varLocal in varDecl.Locals) {
AddGhostVarDecl(varLocal.Name, varLocal.Type, varLocal.IsGhost);
}
if (varDecl.Update != null) {
Util.Assert(varDecl.Update is UpdateStmt || varDecl.Update is AssignSuchThatStmt);
AddGhostStatement((Statement)varDecl.Update, attrs);
//Util.Assert(varDecl.Update.Lhss.Count() == 1);
//var destVar = AsVar(varDecl.Update.Lhss[0]);
//Util.Assert(destVar != null);
//ExprRhs expRhs = ((UpdateStmt)varDecl.Update).Rhss[0] as ExprRhs;
//if (expRhs != null) {
// stmts.Add(new RtlGhostMove(new RtlVar[] { destVar },
// new RtlExp[] { GhostExpression(expRhs.Expr) }));
//} else {
// throw new Exception("not implemented: " + ((UpdateStmt)varDecl.Update).Rhss[0]);
//}
}
}
else if (minVerify)
{
return;
}
else if (assignStmt != null)
{
ExprRhs expRhs = assignStmt.Rhs as ExprRhs;
if (expRhs != null)
{
MemberSelectExpr memberSelect = assignStmt.Lhs as MemberSelectExpr;
RtlVar destVar;
if (memberSelect != null && memberSelect.Member is Field)
{
// assume that this is a global variable; we don't support objects yet
destVar = new RtlVar(GhostVar(memberSelect.MemberName), true, memberSelect.Type);
}
else
{
destVar = AsVar(assignStmt.Lhs);
Util.Assert(destVar != null);
}
stmts.Add(new RtlGhostMove(new RtlVar[] { destVar },
new RtlExp[] { GhostExpression(expRhs.Expr) }));
}
else
{
throw new Exception("not implemented: " + assignStmt.Rhs);
}
}
else if (callStmt != null)
{
var extraTypeargs = GetTypeArgs(attrs);
var extraTypeargsDict = extraTypeargs.Select((t,index) => Tuple.Create(new TypeParameter(callStmt.Tok, "Fake" + index),t)).ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
var subst = callStmt.MethodSelect.TypeArgumentSubstitutions().Concat(extraTypeargsDict);
AddGhostCall(callStmt.Lhs.ConvertAll(AsVar), callStmt.Args,
dafnySpec.Compile_Method((Method)callStmt.MethodSelect.Member,
subst.ToDictionary(p => p.Key, p => AppType(p.Value)),
extraTypeargsDict.Keys.ToList()),
DafnySpec.IsHeapMethod((Method)callStmt.MethodSelect.Member));
SymdiffLinearityPoint();
}
else if (ifStmt != null)
{
stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ") {",
new RtlExp[] { GhostExpression(ifStmt.Guard) }));
Indent();
AddGhostStatement(ifStmt.Thn, attrs);
Unindent();
stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
if (ifStmt.Els != null)
{
stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ") {",
new RtlExp[] {
GhostExpression(new UnaryOpExpr(Bpl.Token.NoToken, UnaryOpExpr.Opcode.Not, ifStmt.Guard)) }));
Indent();
AddGhostStatement(ifStmt.Els, attrs);
Unindent();
stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
}
}
else if (assertStmt != null)
{
stmts.Add(new RtlAssert(GhostExpression(assertStmt.Expr)));
}
else if (forallStmt != null)
{
var oldRenamer = PushRename(forallStmt.BoundVars.Select(v => v.Name));
RtlExp ens = new RtlLiteral("true");
foreach (var e in forallStmt.Ens)
{
ens = new RtlBinary("&&", ens, GhostExpression(e.E));
}
RtlExp range = (forallStmt.Range == null) ? new RtlLiteral("true")
: GhostExpression(forallStmt.Range);
List<RtlExp> wellFormed = GetTypeWellFormed(forallStmt.BoundVars.
Select(x => Tuple.Create(GhostVar(x.Name), x.IsGhost, x.Type)).ToList());
wellFormed.ForEach(e => range = new RtlBinary("&&", e, range));
ens = new RtlBinary("==>", range, ens);
string vars = String.Join(", ", forallStmt.BoundVars.Select(x => GhostVar(x.Name) + ":" +
TypeString(AppType(x.Type))));
stmts.Add(new RtlGhostStmtComputed(s => "forall " + vars + "::(" + s.args[0] + ")",
new List<RtlExp> { ens }));
stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
Indent();
stmts.Add(PushForall());
stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ")",
new List<RtlExp> { range }));
stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
Indent();
AddGhostStatement(forallStmt.Body, attrs);
foreach (var e in forallStmt.Ens)
{
stmts.Add(new RtlAssert(GhostExpression(e.E)));
}
PopForall();
Unindent();
stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
Unindent();
stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
PopRename(oldRenamer);
}
else if (existsStmt != null)
{
List<RtlStmt> assigns = new List<RtlStmt>();
List<RtlVar> tmps = new List<RtlVar>();
List<Tuple<string,bool,Type>> varTuples = new List<Tuple<string,bool,Type>>();
var oldRenamer = PushRename();
foreach (var lhs in existsStmt.Lhss)
{
IdentifierExpr idExp = lhs.Resolved as IdentifierExpr;
RtlVar origVar = AsVar(lhs);
AddRename(idExp.Name);
RtlVar renameVar = AsVar(lhs);
tmps.Add(renameVar);
varTuples.Add(Tuple.Create(renameVar.ToString(), true, idExp.Type));
assigns.Add(new RtlGhostMove(new RtlVar[] { origVar },
new RtlExp[] { renameVar }));
}
string vars = String.Join(", ", tmps.Select(x => x.getName() + ":" + TypeString(AppType(x.type))));
stmts.Add(new RtlGhostStmtComputed(s => "exists " + vars + "::(" + s.args[0] + ");",
new List<RtlExp> {
GetTypeWellFormedExp(varTuples.ToList(), "&&", GhostExpression(existsStmt.Expr)) }));
stmts.AddRange(assigns);
PopRename(oldRenamer);
}
else if (calcStmt != null)
{
Util.Assert(calcStmt.Steps.Count == calcStmt.Hints.Count);
CalcStmt.BinaryCalcOp binOp = calcStmt.Op as CalcStmt.BinaryCalcOp;
bool isImply = binOp != null && binOp.Op == BinaryExpr.Opcode.Imp && calcStmt.Steps.Count > 0;
if (isImply)
{
stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ")",
new RtlExp[] { GhostExpression(CalcStmt.Lhs(calcStmt.Steps[0])) }));
stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
Indent();
}
var stepCount = calcStmt.Hints.Last().Body.Count == 0 ? calcStmt.Steps.Count - 1 : calcStmt.Steps.Count;
for (int i = 0; i < stepCount; i++)
{
if (calcStmt.Hints[i] == null)
{
stmts.Add(new RtlAssert(GhostExpression(calcStmt.Steps[i])));
}
else
{
stmts.Add(new RtlGhostStmtComputed(s => "forall::(" + s.args[0] + ")",
new List<RtlExp> { GhostExpression(calcStmt.Steps[i]) }));
stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
Indent();
var dict = new Dictionary<string,RtlVar>();
stmts.Add(new RtlGhostStmtComputed(s => String.Concat(dict.Values.Select(
x => "var " + x.x + ":" + TypeString(x.type) + ";")),
new RtlExp[0]));
forallVars.Add(dict);
AddGhostStatement(calcStmt.Hints[i], attrs);
forallVars.RemoveAt(forallVars.Count - 1);
Unindent();
stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
}
}
if (isImply)
{
Unindent();
stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
}
}
else
{
throw new Exception("not implemented in ghost methods: " + stmt);
}
}