//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//-----------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
// BoogiePL - StandardVisitor.cs
//---------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
namespace Microsoft.Boogie {
[ContractClass(typeof(VisitorContracts))]
///
/// Base for all classes that process the Absy using the visitor pattern.
///
public abstract class Visitor {
///
/// Switches on node.NodeType to call a visitor method that has been specialized for node.
///
/// The Absy node to be visited.
/// Returns null if node is null. Otherwise returns an updated node (possibly a different object).
public abstract Absy/*!*/ Visit(Absy/*!*/ node);
///
/// Transfers the state from one visitor to another. This enables separate visitor instances to cooperative process a single IR.
///
public virtual void TransferStateTo(Visitor targetVisitor) {
}
public virtual IList VisitExprSeq(IList list) {
Contract.Requires(list != null);
Contract.Ensures(Contract.Result>() != null);
lock (list)
{
for (int i = 0, n = list.Count; i < n; i++)
list[i] = (Expr)this.Visit(cce.NonNull(list[i]));
}
return list;
}
}
[ContractClassFor(typeof(Visitor))]
abstract class VisitorContracts : Visitor {
public override Absy Visit(Absy node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
throw new System.NotImplementedException();
}
}
///
/// Walks an IR, mutating it into a new form. (For a subclass that does not mutate the IR, see ReadOnlyVisitor.)
///
public abstract class StandardVisitor : Visitor {
public Visitor callingVisitor;
public StandardVisitor() {
}
public StandardVisitor(Visitor callingVisitor) {
this.callingVisitor = callingVisitor;
}
public override Absy Visit(Absy node) {
return node.StdDispatch(this);
}
public virtual Cmd VisitAssertCmd(AssertCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Expr = this.VisitExpr(node.Expr);
return node;
}
public virtual Cmd VisitAssignCmd(AssignCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0; i < node.Lhss.Count; ++i) {
node.SetLhs(i, cce.NonNull((AssignLhs)this.Visit(node.Lhss[i])));
node.SetRhs(i, cce.NonNull((Expr/*!*/)this.Visit(node.Rhss[i])));
}
return node;
}
public virtual Cmd VisitAssumeCmd(AssumeCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Expr = this.VisitExpr(node.Expr);
return node;
}
public virtual AtomicRE VisitAtomicRE(AtomicRE node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.b = this.VisitBlock(node.b);
return node;
}
public virtual Axiom VisitAxiom(Axiom node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Expr = this.VisitExpr(node.Expr);
return node;
}
public virtual Type VisitBasicType(BasicType node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return this.VisitType(node);
}
public virtual Expr VisitBvConcatExpr(BvConcatExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.E0 = this.VisitExpr(node.E0);
node.E1 = this.VisitExpr(node.E1);
return node;
}
public virtual Type VisitBvType(BvType node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return this.VisitType(node);
}
public virtual Type VisitBvTypeProxy(BvTypeProxy node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
// if the type proxy is instantiated with some more
// specific type, we visit the instantiation
if (node.ProxyFor != null)
return (Type)this.Visit(node.ProxyFor);
return this.VisitType(node);
}
public virtual Block VisitBlock(Block node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Cmds = this.VisitCmdSeq(node.Cmds);
node.TransferCmd = (TransferCmd)this.Visit(cce.NonNull(node.TransferCmd));
return node;
}
public virtual Expr VisitCodeExpr(CodeExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.LocVars = this.VisitVariableSeq(node.LocVars);
node.Blocks = this.VisitBlockList(node.Blocks);
return node;
}
public virtual List VisitBlockSeq(List blockSeq) {
Contract.Requires(blockSeq != null);
Contract.Ensures(Contract.Result>() != null);
lock (blockSeq)
{
for (int i = 0, n = blockSeq.Count; i < n; i++)
blockSeq[i] = this.VisitBlock(cce.NonNull(blockSeq[i]));
}
return blockSeq;
}
public virtual List/*!*/ VisitBlockList(List/*!*/ blocks) {
Contract.Requires(blocks != null);
Contract.Ensures(Contract.Result>() != null);
for (int i = 0, n = blocks.Count; i < n; i++) {
blocks[i] = this.VisitBlock(blocks[i]);
}
return blocks;
}
public virtual BoundVariable VisitBoundVariable(BoundVariable node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (BoundVariable)this.VisitVariable(node);
return node;
}
public virtual Cmd VisitCallCmd(CallCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0; i < node.Ins.Count; ++i)
if (node.Ins[i] != null)
node.Ins[i] = this.VisitExpr(cce.NonNull(node.Ins[i]));
for (int i = 0; i < node.Outs.Count; ++i)
if (node.Outs[i] != null)
node.Outs[i] = (IdentifierExpr)this.VisitIdentifierExpr(cce.NonNull(node.Outs[i]));
return node;
}
public virtual Cmd VisitParCallCmd(ParCallCmd node)
{
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0; i < node.CallCmds.Count; i++)
{
if (node.CallCmds[i] != null)
node.CallCmds[i] = (CallCmd)this.VisitCallCmd(node.CallCmds[i]);
}
return node;
}
public virtual List VisitCmdSeq(List cmdSeq) {
Contract.Requires(cmdSeq != null);
Contract.Ensures(Contract.Result>() != null);
lock (cmdSeq)
{
for (int i = 0, n = cmdSeq.Count; i < n; i++)
cmdSeq[i] = (Cmd)this.Visit(cce.NonNull(cmdSeq[i])); // call general Visit so subtypes of Cmd get visited by their particular visitor
}
return cmdSeq;
}
public virtual Choice VisitChoice(Choice node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.rs = this.VisitRESeq(node.rs);
return node;
}
public virtual Cmd VisitCommentCmd(CommentCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual Constant VisitConstant(Constant node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual CtorType VisitCtorType(CtorType node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
lock (node)
{
for (int i = 0; i < node.Arguments.Count; ++i)
node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
}
return node;
}
public virtual Declaration VisitDeclaration(Declaration node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual List/*!*/ VisitDeclarationList(List/*!*/ declarationList) {
Contract.Requires(declarationList != null);
Contract.Ensures(Contract.Result>() != null);
for (int i = 0, n = declarationList.Count; i < n; i++)
declarationList[i] = cce.NonNull((Declaration/*!*/)this.Visit(declarationList[i]));
return declarationList;
}
public virtual DeclWithFormals VisitDeclWithFormals(DeclWithFormals node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.InParams = this.VisitVariableSeq(node.InParams);
node.OutParams = this.VisitVariableSeq(node.OutParams);
return node;
}
public virtual Expr VisitExistsExpr(ExistsExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (ExistsExpr)this.VisitQuantifierExpr(node);
return node;
}
public virtual Expr VisitBvExtractExpr(BvExtractExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Bitvector = this.VisitExpr(node.Bitvector);
return node;
}
public virtual Expr VisitExpr(Expr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
Expr e = (Expr)this.Visit(node);
return e;
}
public override IList VisitExprSeq(IList exprSeq) {
//Contract.Requires(exprSeq != null);
Contract.Ensures(Contract.Result>() != null);
for (int i = 0, n = exprSeq.Count; i < n; i++)
exprSeq[i] = this.VisitExpr(cce.NonNull(exprSeq[i]));
return exprSeq;
}
public virtual Requires VisitRequires(Requires @requires) {
Contract.Requires(@requires != null);
Contract.Ensures(Contract.Result() != null);
@requires.Condition = this.VisitExpr(@requires.Condition);
return @requires;
}
public virtual List VisitRequiresSeq(List requiresSeq) {
Contract.Requires(requiresSeq != null);
Contract.Ensures(Contract.Result>() != null);
for (int i = 0, n = requiresSeq.Count; i < n; i++)
requiresSeq[i] = this.VisitRequires(requiresSeq[i]);
return requiresSeq;
}
public virtual Ensures VisitEnsures(Ensures @ensures) {
Contract.Requires(@ensures != null);
Contract.Ensures(Contract.Result() != null);
@ensures.Condition = this.VisitExpr(@ensures.Condition);
return @ensures;
}
public virtual List VisitEnsuresSeq(List ensuresSeq) {
Contract.Requires(ensuresSeq != null);
Contract.Ensures(Contract.Result>() != null);
for (int i = 0, n = ensuresSeq.Count; i < n; i++)
ensuresSeq[i] = this.VisitEnsures(ensuresSeq[i]);
return ensuresSeq;
}
public virtual Expr VisitForallExpr(ForallExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (ForallExpr)this.VisitQuantifierExpr(node);
return node;
}
public virtual Expr VisitLambdaExpr(LambdaExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (LambdaExpr)this.VisitBinderExpr(node);
return node;
}
public virtual Formal VisitFormal(Formal node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual Function VisitFunction(Function node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (Function)this.VisitDeclWithFormals(node);
if (node.Body != null)
node.Body = this.VisitExpr(node.Body);
return node;
}
public virtual GlobalVariable VisitGlobalVariable(GlobalVariable node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (GlobalVariable)this.VisitVariable(node);
return node;
}
public virtual GotoCmd VisitGotoCmd(GotoCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
// do not visit the labelTargets, or control-flow loops will lead to a looping visitor
return node;
}
public virtual Cmd VisitHavocCmd(HavocCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Vars = this.VisitIdentifierExprSeq(node.Vars);
return node;
}
public virtual Expr VisitIdentifierExpr(IdentifierExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
if (node.Decl != null)
node.Decl = this.VisitVariable(node.Decl);
return node;
}
public virtual List VisitIdentifierExprSeq(List identifierExprSeq) {
Contract.Requires(identifierExprSeq != null);
Contract.Ensures(Contract.Result>() != null);
lock (identifierExprSeq)
{
for (int i = 0, n = identifierExprSeq.Count; i < n; i++)
identifierExprSeq[i] = (IdentifierExpr)this.VisitIdentifierExpr(cce.NonNull(identifierExprSeq[i]));
}
return identifierExprSeq;
}
public virtual Implementation VisitImplementation(Implementation node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.LocVars = this.VisitVariableSeq(node.LocVars);
node.Blocks = this.VisitBlockList(node.Blocks);
node.Proc = this.VisitProcedure(cce.NonNull(node.Proc));
node = (Implementation)this.VisitDeclWithFormals(node); // do this first or last?
return node;
}
public virtual Expr VisitLiteralExpr(LiteralExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual LocalVariable VisitLocalVariable(LocalVariable node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual AssignLhs VisitMapAssignLhs(MapAssignLhs node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Map = cce.NonNull((AssignLhs)this.Visit(node.Map));
for (int i = 0; i < node.Indexes.Count; ++i)
node.Indexes[i] = cce.NonNull((Expr)this.Visit(node.Indexes[i]));
return node;
}
public virtual MapType VisitMapType(MapType node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
// not doing anything about the bound variables ... maybe
// these should be visited as well ...
//
// NOTE: when overriding this method, you have to make sure that
// the bound variables of the map type are updated correctly
lock (node.Arguments)
{
for (int i = 0; i < node.Arguments.Count; ++i)
node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
}
node.Result = cce.NonNull((Type/*!*/)this.Visit(node.Result));
return node;
}
public virtual Type VisitMapTypeProxy(MapTypeProxy node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
// if the type proxy is instantiated with some more
// specific type, we visit the instantiation
if (node.ProxyFor != null)
return (Type)this.Visit(node.ProxyFor);
return this.VisitType(node);
}
public virtual Expr VisitNAryExpr(NAryExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Args = this.VisitExprSeq(node.Args);
return node;
}
public virtual Expr VisitOldExpr(OldExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Expr = this.VisitExpr(node.Expr);
return node;
}
public virtual Procedure VisitProcedure(Procedure node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Ensures = this.VisitEnsuresSeq(node.Ensures);
node.InParams = this.VisitVariableSeq(node.InParams);
node.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
node.OutParams = this.VisitVariableSeq(node.OutParams);
node.Requires = this.VisitRequiresSeq(node.Requires);
return node;
}
public virtual Program VisitProgram(Program node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
var decls = node.TopLevelDeclarations.ToList();
node.ClearTopLevelDeclarations();
node.AddTopLevelDeclarations(this.VisitDeclarationList(decls));
return node;
}
public virtual QKeyValue VisitQKeyValue(QKeyValue node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
var newParams = new List