/// <summary> /// Does not print LHS /// </summary> void PrintUpdateRHS(ConcreteUpdateStatement s) { Contract.Requires(s != null); if (s is UpdateStmt) { var update = (UpdateStmt)s; if (update.Lhss.Count != 0) { wr.Write(" := "); } var sep = ""; foreach (var rhs in update.Rhss) { wr.Write(sep); PrintRhs(rhs); sep = ", "; } } else if (s is AssignSuchThatStmt) { var update = (AssignSuchThatStmt)s; wr.Write(" :| "); if (update.AssumeToken != null) { wr.Write("assume "); } PrintExpression(update.Expr, true); } else { Contract.Assert(s == null); // otherwise, unknown type } }
// Checks that statement stmt, defined in the constructed module m, is a refinement of skip in the parent module void CheckIsOkayUpdateStmt(ConcreteUpdateStatement stmt, ModuleDefinition m) { foreach (var lhs in stmt.Lhss) { var l = lhs.Resolved; if (l is IdentifierExpr) { var ident = (IdentifierExpr)l; Contract.Assert(ident.Var is LocalVariable || ident.Var is Formal); // LHS identifier expressions must be locals or out parameters (ie. formals) if ((ident.Var is LocalVariable && RefinementToken.IsInherited(((LocalVariable)ident.Var).Tok, m)) || ident.Var is Formal) { // for some reason, formals are not considered to be inherited. reporter.Error(MessageSource.RefinementTransformer, l.tok, "refinement method cannot assign to variable defined in parent module ('{0}')", ident.Var.Name); } } else if (l is MemberSelectExpr) { var member = ((MemberSelectExpr)l).Member; if (RefinementToken.IsInherited(member.tok, m)) { reporter.Error(MessageSource.RefinementTransformer, l.tok, "refinement method cannot assign to a field defined in parent module ('{0}')", member.Name); } } else { // must be an array element reporter.Error(MessageSource.RefinementTransformer, l.tok, "new assignments in a refinement method can only assign to state that the module defines (which never includes array elements)"); } } if (stmt is UpdateStmt) { var s = (UpdateStmt)stmt; foreach (var rhs in s.Rhss) { if (rhs.CanAffectPreviouslyKnownExpressions) { reporter.Error(MessageSource.RefinementTransformer, rhs.Tok, "assignment RHS in refinement method is not allowed to affect previously defined state"); } } } }