public CalcStmt.CalcOp CloneCalcOp(CalcStmt.CalcOp op) { if (op is CalcStmt.BinaryCalcOp) { return new CalcStmt.BinaryCalcOp(((CalcStmt.BinaryCalcOp) op).Op); } else if (op is CalcStmt.TernaryCalcOp) { return new CalcStmt.TernaryCalcOp(CloneExpr(((CalcStmt.TernaryCalcOp) op).Index)); } else { Contract.Assert(false); throw new cce.UnreachableException(); } }
public string GenerateString(CalcStmt statement, int tabs) { StringBuilder bob = new StringBuilder(); ApplyIndentation(bob, tabs); bob.AppendLine(statement.Tok.val); ApplyIndentation(bob, tabs); bob.AppendLine("{"); //ApplyIndentation(bob, tabs + 1); int numOfSteps = statement.Steps.Count; // Print all steps and hints. for (int i = 0; i < numOfSteps; i++) { if (i > 0) { bob.AppendLine(); } ApplyIndentation(bob, tabs + 1); bob.AppendLine(GenerateString(statement.Lines[i]) + ";"); ApplyIndentation(bob, tabs); if (i < numOfSteps - 1) { bob.Append(GenerateString(statement.StepOps[i])); } BlockStmt currHint = statement.Hints[i]; if (currHint.Body != null && currHint.Body.Count > 0) { bob.Append(" "); bob.Append(GenerateString(currHint, 0, true)); } } ApplyIndentation(bob, tabs - 1); bob.AppendLine("}"); return(bob.ToString()); //return string.Empty; }
private void FindRemovableTypesInCalcStmt(CalcStmt calc, Statement parent, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { Wrap <Statement> calcWrap = null; if (parent is BlockStmt) { calcWrap = new Wrap <Statement>(calc, ((BlockStmt)parent).Body); } else if (parent is MatchStmt) { var matchStmt = (MatchStmt)parent; foreach (var matchCase in matchStmt.Cases) { if (!matchCase.Body.Contains(calc)) { continue; } calcWrap = new Wrap <Statement>(calc, matchCase.Body); break; } if (calcWrap == null) { throw new Exception("Calc not found!"); } } else { throw new Exception("Calc not found!"); } _allRemovableTypes.AddCalc(calcWrap, method); foreach (var hint in calc.Hints) { FindRemovableTypesInStatement(hint, calc, method, wildCardParent, classDecl); // This will check the inside of the hint - it will ID anything that can be shortened inside it. } }
void CalcStmt(out Statement s) { Contract.Ensures(Contract.ValueAtReturn(out s) != null); Token x; Attributes attrs = null; CalcStmt.CalcOp op, calcOp = Microsoft.Dafny.CalcStmt.DefaultOp, resOp = Microsoft.Dafny.CalcStmt.DefaultOp; var lines = new List<Expression>(); var hints = new List<BlockStmt>(); CalcStmt.CalcOp stepOp; var stepOps = new List<CalcStmt.CalcOp>(); CalcStmt.CalcOp maybeOp; Expression e; IToken opTok; IToken danglingOperator = null; Expect(32); x = t; while (IsAttribute()) { Attribute(ref attrs); } if (StartOf(25)) { CalcOp(out opTok, out calcOp); maybeOp = calcOp.ResultOp(calcOp); // guard against non-transitive calcOp (like !=) if (maybeOp == null) { SemErr(opTok, "the main operator of a calculation must be transitive"); } resOp = calcOp; } Expect(46); while (StartOf(7)) { Expression(out e, false, true); lines.Add(e); stepOp = calcOp; danglingOperator = null; Expect(28); if (StartOf(25)) { CalcOp(out opTok, out op); maybeOp = resOp.ResultOp(op); if (maybeOp == null) { SemErr(opTok, "this operator cannot continue this calculation"); } else { stepOp = op; resOp = maybeOp; danglingOperator = opTok; } } stepOps.Add(stepOp); var subhints = new List<Statement>(); IToken hintStart = la; IToken hintEnd = hintStart; IToken t0, t1; BlockStmt subBlock; Statement subCalc; while (la.kind == _lbrace || la.kind == _calc) { if (la.kind == 46) { BlockStmt(out subBlock, out t0, out t1); hintEnd = subBlock.EndTok; subhints.Add(subBlock); } else if (la.kind == 32) { CalcStmt(out subCalc); hintEnd = subCalc.EndTok; subhints.Add(subCalc); } else SynErr(192); } var h = new BlockStmt(hintStart, hintEnd, subhints); // if the hint is empty, hintStart is the first token of the next line, but it doesn't matter because the block statement is just used as a container hints.Add(h); if (h.Body.Count != 0) { danglingOperator = null; } } Expect(47); if (danglingOperator != null) { SemErr(danglingOperator, "a calculation cannot end with an operator"); } if (lines.Count > 0) { // Repeat the last line to create a dummy line for the dangling hint lines.Add(lines[lines.Count - 1]); } s = new CalcStmt(x, t, calcOp, lines, hints, stepOps, resOp, attrs); }
void CalcOp(out IToken x, out CalcStmt.CalcOp/*!*/ op) { var binOp = BinaryExpr.Opcode.Eq; // Returns Eq if parsing fails because it is compatible with any other operator Expression k = null; x = null; switch (la.kind) { case 54: { Get(); x = t; binOp = BinaryExpr.Opcode.Eq; if (la.kind == 106) { Get(); Expect(48); Expression(out k, true, true); Expect(49); } break; } case 52: { Get(); x = t; binOp = BinaryExpr.Opcode.Lt; break; } case 53: { Get(); x = t; binOp = BinaryExpr.Opcode.Gt; break; } case 107: { Get(); x = t; binOp = BinaryExpr.Opcode.Le; break; } case 108: { Get(); x = t; binOp = BinaryExpr.Opcode.Ge; break; } case 55: { Get(); x = t; binOp = BinaryExpr.Opcode.Neq; break; } case 56: { Get(); x = t; binOp = BinaryExpr.Opcode.Neq; break; } case 109: { Get(); x = t; binOp = BinaryExpr.Opcode.Le; break; } case 110: { Get(); x = t; binOp = BinaryExpr.Opcode.Ge; break; } case 111: case 112: { EquivOp(); x = t; binOp = BinaryExpr.Opcode.Iff; break; } case 113: case 114: { ImpliesOp(); x = t; binOp = BinaryExpr.Opcode.Imp; break; } case 115: case 116: { ExpliesOp(); x = t; binOp = BinaryExpr.Opcode.Exp; break; } default: SynErr(209); break; } if (k == null) { op = new Microsoft.Dafny.CalcStmt.BinaryCalcOp(binOp); } else { op = new Microsoft.Dafny.CalcStmt.TernaryCalcOp(k); } }
void PrintCalcOp(CalcStmt.CalcOp op) { Contract.Requires(op != null); wr.Write(op.ToString()); if (op is CalcStmt.TernaryCalcOp) { wr.Write("["); PrintExpression(((CalcStmt.TernaryCalcOp) op).Index, false); wr.Write("]"); } }
public virtual Statement CloneStmt(Statement stmt) { if (stmt == null) { return null; } Statement r; if (stmt is AssertStmt) { var s = (AssertStmt)stmt; r = new AssertStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null); } else if (stmt is AssumeStmt) { var s = (AssumeStmt)stmt; r = new AssumeStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null); } else if (stmt is TacticInvariantStmt) { var s = (TacticInvariantStmt)stmt; r = new TacticInvariantStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null, s.IsObjectLevel); } else if (stmt is TacticAssertStmt) { var s = (TacticAssertStmt)stmt; r = new TacticAssertStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Expr), null, s.IsObjectLevel); } else if (stmt is PrintStmt) { var s = (PrintStmt)stmt; r = new PrintStmt(Tok(s.Tok), Tok(s.EndTok), s.Args.ConvertAll(CloneExpr)); } else if (stmt is BreakStmt) { var s = (BreakStmt)stmt; if (s.TargetLabel != null) { r = new BreakStmt(Tok(s.Tok), Tok(s.EndTok), s.TargetLabel); } else { r = new BreakStmt(Tok(s.Tok), Tok(s.EndTok), s.BreakCount); } } else if (stmt is ReturnStmt) { var s = (ReturnStmt)stmt; r = new ReturnStmt(Tok(s.Tok), Tok(s.EndTok), s.rhss == null ? null : s.rhss.ConvertAll(CloneRHS)); } else if (stmt is YieldStmt) { var s = (YieldStmt)stmt; r = new YieldStmt(Tok(s.Tok), Tok(s.EndTok), s.rhss == null ? null : s.rhss.ConvertAll(CloneRHS)); } else if (stmt is AssignStmt) { var s = (AssignStmt)stmt; r = new AssignStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Lhs), CloneRHS(s.Rhs)); } else if (stmt is BlockStmt) { r = CloneBlockStmt((BlockStmt)stmt); } else if (stmt is IfStmt) { var s = (IfStmt)stmt; r = new IfStmt(Tok(s.Tok), Tok(s.EndTok), s.IsExistentialGuard, CloneExpr(s.Guard), CloneBlockStmt(s.Thn), CloneStmt(s.Els)); } else if (stmt is AlternativeStmt) { var s = (AlternativeStmt)stmt; r = new AlternativeStmt(Tok(s.Tok), Tok(s.EndTok), s.Alternatives.ConvertAll(CloneGuardedAlternative)); } else if (stmt is WhileStmt) { var s = (WhileStmt)stmt; r = new WhileStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Guard), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), CloneBlockStmt(s.Body)); ((WhileStmt)r).TacAps = s.TacAps; } else if (stmt is AlternativeLoopStmt) { var s = (AlternativeLoopStmt)stmt; r = new AlternativeLoopStmt(Tok(s.Tok), Tok(s.EndTok), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), s.Alternatives.ConvertAll(CloneGuardedAlternative)); } else if (stmt is ForallStmt) { var s = (ForallStmt)stmt; r = new ForallStmt(Tok(s.Tok), Tok(s.EndTok), s.BoundVars.ConvertAll(CloneBoundVar), null, CloneExpr(s.Range), s.Ens.ConvertAll(CloneMayBeFreeExpr), CloneStmt(s.Body)); if (s.ForallExpressions != null) { ((ForallStmt)r).ForallExpressions = s.ForallExpressions.ConvertAll(CloneExpr); } } else if (stmt is CalcStmt) { var s = (CalcStmt)stmt; // calc statements have the unusual property that the last line is duplicated. If that is the case (which // we expect it to be here), we share the clone of that line as well. var lineCount = s.Lines.Count; var lines = new List<Expression>(lineCount); for (int i = 0; i < lineCount; i++) { lines.Add(i == lineCount - 1 && 2 <= lineCount && s.Lines[i] == s.Lines[i - 1] ? lines[i - 1] : CloneExpr(s.Lines[i])); } Contract.Assert(lines.Count == lineCount); r = new CalcStmt(Tok(s.Tok), Tok(s.EndTok), CloneCalcOp(s.Op), lines, s.Hints.ConvertAll(CloneBlockStmt), s.StepOps.ConvertAll(CloneCalcOp), CloneCalcOp(s.ResultOp), CloneAttributes(s.Attributes)); } else if (stmt is MatchStmt) { var s = (MatchStmt)stmt; r = new MatchStmt(Tok(s.Tok), Tok(s.EndTok), CloneExpr(s.Source), s.Cases.ConvertAll(CloneMatchCaseStmt), s.UsesOptionalBraces); } else if (stmt is AssignSuchThatStmt) { var s = (AssignSuchThatStmt)stmt; r = new AssignSuchThatStmt(Tok(s.Tok), Tok(s.EndTok), s.Lhss.ConvertAll(CloneExpr), CloneExpr(s.Expr), s.AssumeToken == null ? null : Tok(s.AssumeToken), null); } else if (stmt is UpdateStmt) { var s = (UpdateStmt)stmt; r = new UpdateStmt(Tok(s.Tok), Tok(s.EndTok), s.Lhss.ConvertAll(CloneExpr), s.Rhss.ConvertAll(CloneRHS), s.CanMutateKnownState); } else if (stmt is VarDeclStmt) { var s = (VarDeclStmt)stmt; var lhss = s.Locals.ConvertAll(c => new LocalVariable(Tok(c.Tok), Tok(c.EndTok), c.Name, CloneType(c.OptionalType), c.IsGhost)); r = new VarDeclStmt(Tok(s.Tok), Tok(s.EndTok), lhss, (ConcreteUpdateStatement)CloneStmt(s.Update)); } else if (stmt is LetStmt) { var s = (LetStmt)stmt; r = new LetStmt(Tok(s.Tok), Tok(s.EndTok), s.LHSs.ConvertAll(CloneCasePattern), s.RHSs.ConvertAll(CloneExpr)); } else if (stmt is ModifyStmt) { var s = (ModifyStmt)stmt; var mod = CloneSpecFrameExpr(s.Mod); var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new ModifyStmt(Tok(s.Tok), Tok(s.EndTok), mod.Expressions, mod.Attributes, body); } else if (stmt is TacnyCasesBlockStmt) { var s = (TacnyCasesBlockStmt)stmt; var guard = CloneExpr(s.Guard); var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new TacnyCasesBlockStmt(Tok(s.Tok), Tok(s.EndTok), guard, body); } else if (stmt is TacnyChangedBlockStmt) { var s = (TacnyChangedBlockStmt)stmt; var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new TacnyChangedBlockStmt(Tok(s.Tok), Tok(s.EndTok), body); } else if (stmt is TacnySolvedBlockStmt) { var s = (TacnySolvedBlockStmt)stmt; var body = s.Body == null ? null : CloneBlockStmt(s.Body); r = new TacnySolvedBlockStmt(Tok(s.Tok), Tok(s.EndTok), body); } else if (stmt is TacnyTryCatchBlockStmt) { var s = (TacnyTryCatchBlockStmt)stmt; var body = s.Body == null ? null : CloneBlockStmt(s.Body); var c = s.Ctch == null ? null : CloneBlockStmt(s.Ctch); r = new TacnyTryCatchBlockStmt(Tok(s.Tok), Tok(s.EndTok), body, c); } else if (stmt is TacticVarDeclStmt) { var s = (TacticVarDeclStmt)stmt; var lhss = s.Locals.ConvertAll(c => new LocalVariable(Tok(c.Tok), Tok(c.EndTok), c.Name, CloneType(c.OptionalType), c.IsGhost)); r = new TacticVarDeclStmt(Tok(s.Tok), Tok(s.EndTok), lhss, (ConcreteUpdateStatement)CloneStmt(s.Update)); } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected statement } // add labels to the cloned statement AddStmtLabels(r, stmt.Labels); r.Attributes = CloneAttributes(stmt.Attributes); return r; }
public virtual void AddResolvedGhostStatement(Statement stmt) { 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; VarDecl varDecl = stmt as VarDecl; CalcStmt calcStmt = stmt as CalcStmt; ForallStmt forallStmt = stmt as ForallStmt; AssignSuchThatStmt existsStmt = stmt as AssignSuchThatStmt; if (block != null) { var oldRenamer = PushRename(); block.Body.ForEach(AddGhostStatement); PopRename(oldRenamer); } else if (varDecl != null) { AddGhostVarDecl(varDecl.Name, varDecl.Type, varDecl.IsGhost); } else if (minVerify) { return; } else if (assignStmt != null) { ExprRhs expRhs = assignStmt.Rhs as ExprRhs; if (expRhs != null) { FieldSelectExpr fieldSelect = assignStmt.Lhs as FieldSelectExpr; RtlVar destVar; if (fieldSelect != null) { destVar = new RtlVar(GhostVar(fieldSelect.FieldName), true, fieldSelect.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) { AddGhostCall(callStmt.Lhs.ConvertAll(AsVar), callStmt.Args, dafnySpec.Compile_Method(callStmt.Method, callStmt.TypeArgumentSubstitutions.ToDictionary(p => p.Key, p => AppType(p.Value))), DafnySpec.IsHeapMethod(callStmt.Method)); SymdiffLinearityPoint(); } else if (ifStmt != null) { stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ") {", new RtlExp[] { GhostExpression(ifStmt.Guard) })); Indent(); AddGhostStatement(ifStmt.Thn); 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 UnaryExpr(Bpl.Token.NoToken, UnaryExpr.Opcode.Not, ifStmt.Guard)) })); Indent(); AddGhostStatement(ifStmt.Els); 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); 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]); 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); } }
private void InterpretCalcStmt(CalcStmt stmt) { //InterpertBlockStmt(stmt.); }
private void FindRemovableTypesInCalcStmt(CalcStmt calc, Statement parent, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { Wrap<Statement> calcWrap = null; if (parent is BlockStmt) calcWrap = new Wrap<Statement>(calc, ((BlockStmt)parent).Body); else if (parent is MatchStmt) { var matchStmt = (MatchStmt) parent; foreach (var matchCase in matchStmt.Cases) { if (!matchCase.Body.Contains(calc)) continue; calcWrap = new Wrap<Statement>(calc, matchCase.Body); break; } if (calcWrap == null) throw new Exception("Calc not found!"); } else { throw new Exception("Calc not found!"); } _allRemovableTypes.AddCalc(calcWrap, method); foreach (var hint in calc.Hints) { FindRemovableTypesInStatement(hint, calc, method, wildCardParent, classDecl); // This will check the inside of the hint - it will ID anything that can be shortened inside it. } }