//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//-----------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
// BoogiePL - StandardVisitor.cs
//---------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Diagnostics.Contracts;
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 ExprSeq VisitExprSeq(ExprSeq list) {
Contract.Requires(list != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = list.Length; 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, mutuating it into a new form
///
public abstract class StandardVisitor : Visitor {
public Visitor callingVisitor;
public StandardVisitor() {
}
public StandardVisitor(Visitor callingVisitor) {
this.callingVisitor = callingVisitor;
}
public override Absy Visit(Absy node) {
//Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node.StdDispatch(this);
}
public virtual AIVariableExpr VisitAIVariableExpr(AIVariableExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
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.Lhss[i] = cce.NonNull((AssignLhs)this.Visit(node.Lhss[i]));
node.Rhss[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 BvConcatExpr 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 BlockSeq VisitBlockSeq(BlockSeq blockSeq) {
Contract.Requires(blockSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = blockSeq.Length; i < n; i++)
blockSeq[i] = this.VisitBlock(cce.NonNull(blockSeq[i]));
return blockSeq;
}
public virtual List/*!*/ VisitBlockList(List/*!*/ blocks) {
Contract.Requires(cce.NonNullElements(blocks));
Contract.Ensures(cce.NonNullElements(Contract.Result>()));
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 VisitCallForallCmd(CallForallCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
List elist = new List(node.Ins.Count);
foreach (Expr arg in node.Ins) {
if (arg == null) {
elist.Add(null);
} else {
elist.Add(this.VisitExpr(arg));
}
}
node.Ins = elist;
node.Proc = this.VisitProcedure(cce.NonNull(node.Proc));
return node;
}
public virtual CmdSeq VisitCmdSeq(CmdSeq cmdSeq) {
Contract.Requires(cmdSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = cmdSeq.Length; 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);
for (int i = 0; i < node.Arguments.Length; ++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(cce.NonNullElements(declarationList));
Contract.Ensures(cce.NonNullElements(Contract.Result>()));
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 ExistsExpr VisitExistsExpr(ExistsExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (ExistsExpr)this.VisitQuantifierExpr(node);
return node;
}
public virtual BvExtractExpr 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 ExprSeq VisitExprSeq(ExprSeq exprSeq) {
//Contract.Requires(exprSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = exprSeq.Length; 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 RequiresSeq VisitRequiresSeq(RequiresSeq requiresSeq) {
Contract.Requires(requiresSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = requiresSeq.Length; 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 EnsuresSeq VisitEnsuresSeq(EnsuresSeq ensuresSeq) {
Contract.Requires(ensuresSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = ensuresSeq.Length; i < n; i++)
ensuresSeq[i] = this.VisitEnsures(ensuresSeq[i]);
return ensuresSeq;
}
public virtual ForallExpr VisitForallExpr(ForallExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = (ForallExpr)this.VisitQuantifierExpr(node);
return node;
}
public virtual LambdaExpr 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 IdentifierExprSeq VisitIdentifierExprSeq(IdentifierExprSeq identifierExprSeq) {
Contract.Requires(identifierExprSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = identifierExprSeq.Length; 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 LiteralExpr 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
for (int i = 0; i < node.Arguments.Length; ++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);
node.TopLevelDeclarations = this.VisitDeclarationList(node.TopLevelDeclarations);
return node;
}
public virtual BinderExpr VisitBinderExpr(BinderExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Body = this.VisitExpr(node.Body);
node.Dummies = this.VisitVariableSeq(node.Dummies);
//node.Type = this.VisitType(node.Type);
return node;
}
public virtual QuantifierExpr VisitQuantifierExpr(QuantifierExpr node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node = cce.NonNull((QuantifierExpr)this.VisitBinderExpr(node));
if (node.Triggers != null) {
node.Triggers = this.VisitTrigger(node.Triggers);
}
return node;
}
public virtual Cmd VisitRE(RE node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return (Cmd)this.Visit(node); // Call general visit so subtypes get visited by their particular visitor
}
public virtual RESeq VisitRESeq(RESeq reSeq) {
Contract.Requires(reSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = reSeq.Length; i < n; i++)
reSeq[i] = (RE)this.VisitRE(cce.NonNull(reSeq[i]));
return reSeq;
}
public virtual ReturnCmd VisitReturnCmd(ReturnCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return (ReturnCmd)this.VisitTransferCmd(node);
}
public virtual ReturnExprCmd VisitReturnExprCmd(ReturnExprCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Expr = this.VisitExpr(node.Expr);
return node;
}
public virtual Sequential VisitSequential(Sequential node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.first = (RE)this.VisitRE(node.first);
node.second = (RE)this.VisitRE(node.second);
return node;
}
public virtual AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.AssignedVariable =
(IdentifierExpr)this.VisitIdentifierExpr(node.AssignedVariable);
return node;
}
public virtual Cmd VisitStateCmd(StateCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Locals = this.VisitVariableSeq(node.Locals);
node.Cmds = this.VisitCmdSeq(node.Cmds);
return node;
}
public virtual TransferCmd VisitTransferCmd(TransferCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual Trigger VisitTrigger(Trigger node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
Trigger origNext = node.Next;
if (origNext != null) {
Trigger newNext = this.VisitTrigger(origNext);
if (newNext != origNext) {
node = new Trigger(node.tok, node.Pos, node.Tr); // note: this creates sharing between the old and new Tr sequence
node.Next = newNext;
}
}
node.Tr = this.VisitExprSeq(node.Tr);
return node;
}
// called by default for all nullary type constructors and type variables
public virtual Type VisitType(Type node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return node;
}
public virtual TypedIdent VisitTypedIdent(TypedIdent node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Type = (Type)this.Visit(node.Type);
return node;
}
public virtual Declaration VisitTypeCtorDecl(TypeCtorDecl node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return this.VisitDeclaration(node);
}
public virtual Type VisitTypeSynonymAnnotation(TypeSynonymAnnotation node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.ExpandedType = cce.NonNull((Type/*!*/)this.Visit(node.ExpandedType));
for (int i = 0; i < node.Arguments.Length; ++i)
node.Arguments[i] = cce.NonNull((Type/*!*/)this.Visit(node.Arguments[i]));
return node;
}
public virtual Declaration VisitTypeSynonymDecl(TypeSynonymDecl node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return this.VisitDeclaration(node);
}
public virtual Type VisitTypeVariable(TypeVariable node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return this.VisitType(node);
}
public virtual Type VisitTypeProxy(TypeProxy 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 cce.NonNull((Type/*!*/)this.Visit(node.ProxyFor));
return this.VisitType(node);
}
public virtual Type VisitUnresolvedTypeIdentifier(UnresolvedTypeIdentifier node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
return this.VisitType(node);
}
public virtual Variable VisitVariable(Variable node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.TypedIdent = this.VisitTypedIdent(node.TypedIdent);
return node;
}
public virtual VariableSeq VisitVariableSeq(VariableSeq variableSeq) {
Contract.Requires(variableSeq != null);
Contract.Ensures(Contract.Result() != null);
for (int i = 0, n = variableSeq.Length; i < n; i++)
variableSeq[i] = this.VisitVariable(cce.NonNull(variableSeq[i]));
return variableSeq;
}
public virtual Cmd VisitAssertEnsuresCmd(AssertEnsuresCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Ensures = this.VisitEnsures(node.Ensures);
node.Expr = this.VisitExpr(node.Expr);
return node;
}
public virtual Cmd VisitAssertRequiresCmd(AssertRequiresCmd node) {
Contract.Requires(node != null);
Contract.Ensures(Contract.Result() != null);
node.Requires = this.VisitRequires(node.Requires);
node.Expr = this.VisitExpr(node.Expr);
return node;
}
}
}