public override void TraverseChildren(ISwitchStatement switchStatement)
        {
            var eTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext);

            eTraverser.Traverse(switchStatement.Expression);
            var conditionExpr = eTraverser.TranslatedExpressions.Pop();

            // Can't depend on default case existing or its index in the collection.
            var         switchCases = new List <ISwitchCase>();
            ISwitchCase defaultCase = null;

            foreach (var switchCase in switchStatement.Cases)
            {
                if (switchCase.IsDefault)
                {
                    defaultCase = switchCase;
                }
                else
                {
                    switchCases.Add(switchCase);
                }
            }
            Bpl.StmtList defaultStmts = null;
            if (defaultCase != null)
            {
                var defaultBodyTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
                defaultBodyTraverser.Traverse(defaultCase.Body);
                defaultStmts = defaultBodyTraverser.StmtBuilder.Collect(defaultCase.Token());
            }

            Bpl.IfCmd ifCmd = null;

            for (int i = switchCases.Count - 1; 0 <= i; i--)
            {
                var switchCase = switchCases[i];

                var scTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext);
                scTraverser.Traverse(switchCase.Expression);
                var scConditionExpr = scTraverser.TranslatedExpressions.Pop();
                var condition       = Bpl.Expr.Eq(conditionExpr, scConditionExpr);

                var scBodyTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
                scBodyTraverser.Traverse(switchCase.Body);

                ifCmd = new Bpl.IfCmd(switchCase.Token(),
                                      condition,
                                      scBodyTraverser.StmtBuilder.Collect(switchCase.Token()),
                                      ifCmd,
                                      defaultStmts);
                defaultStmts = null; // default body goes only into the innermost if-then-else
            }
            StmtBuilder.Add(ifCmd);
        }
예제 #2
0
파일: Parser.cs 프로젝트: qunyanm/boogie
	void StmtList(out StmtList/*!*/ stmtList) {
		Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); List<BigBlock/*!*/> bigblocks = new List<BigBlock/*!*/>();
		/* built-up state for the current BigBlock: */
		IToken startToken = null;  string currentLabel = null;
		List<Cmd> cs = null;  /* invariant: startToken != null ==> cs != null */
		/* temporary variables: */
		IToken label;  Cmd c;  BigBlock b;
		StructuredCmd ec = null;  StructuredCmd/*!*/ ecn;
		TransferCmd tc = null;  TransferCmd/*!*/ tcn;
		
		while (StartOf(7)) {
			if (StartOf(8)) {
				LabelOrCmd(out c, out label);
				if (c != null) {
				 // LabelOrCmd read a Cmd
				 Contract.Assert(label == null);
				 if (startToken == null) { startToken = c.tok;  cs = new List<Cmd>(); }
				 Contract.Assert(cs != null);
				 cs.Add(c);
				} else {
				 // LabelOrCmd read a label
				 Contract.Assert(label != null);
				 if (startToken != null) {
				   Contract.Assert(cs != null);
				   // dump the built-up state into a BigBlock
				   b = new BigBlock(startToken, currentLabel, cs, null, null);
				   bigblocks.Add(b);
				   cs = null;
				 }
				 startToken = label;
				 currentLabel = label.val;
				 cs = new List<Cmd>();
				}
				
			} else if (la.kind == 41 || la.kind == 43 || la.kind == 46) {
				StructuredCmd(out ecn);
				ec = ecn;
				if (startToken == null) { startToken = ec.tok;  cs = new List<Cmd>(); }
				Contract.Assert(cs != null);
				b = new BigBlock(startToken, currentLabel, cs, ec, null);
				bigblocks.Add(b);
				startToken = null;  currentLabel = null;  cs = null;
				
			} else {
				TransferCmd(out tcn);
				tc = tcn;
				if (startToken == null) { startToken = tc.tok;  cs = new List<Cmd>(); }
				Contract.Assert(cs != null);
				b = new BigBlock(startToken, currentLabel, cs, null, tc);
				bigblocks.Add(b);
				startToken = null;  currentLabel = null;  cs = null;
				
			}
		}
		Expect(29);
		IToken/*!*/ endCurly = t;
		if (startToken == null && bigblocks.Count == 0) {
		 startToken = t;  cs = new List<Cmd>();
		}
		if (startToken != null) {
		 Contract.Assert(cs != null);
		 b = new BigBlock(startToken, currentLabel, cs, null, null);
		 bigblocks.Add(b);
		}
		
		stmtList = new StmtList(bigblocks, endCurly);
		
	}
예제 #3
0
파일: Parser.cs 프로젝트: qunyanm/boogie
	void ImplBody(out List<Variable>/*!*/ locals, out StmtList/*!*/ stmtList) {
		Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new List<Variable>(); 
		Expect(28);
		while (la.kind == 8) {
			LocalVars(locals);
		}
		StmtList(out stmtList);
	}
예제 #4
0
 private static Bpl.IfCmd BuildIfCmd(Bpl.Expr b, Bpl.Cmd cmd, Bpl.StmtList stmts)
 {
     Bpl.StmtListBuilder ifStmtBuilder = new Bpl.StmtListBuilder();
     ifStmtBuilder.Add(cmd);
     return(new Bpl.IfCmd(b.tok, b, ifStmtBuilder.Collect(b.tok), null, stmts));
 }
예제 #5
0
 void NameAnonymousBlocks(StmtList stmtList)
 {
     Contract.Requires(stmtList != null);
       foreach (BigBlock b in stmtList.BigBlocks) {
     if (b.LabelName == null) {
       b.LabelName = prefix + anon;
       anon++;
     }
     if (b.ec is WhileCmd) {
       WhileCmd wcmd = (WhileCmd)b.ec;
       NameAnonymousBlocks(wcmd.Body);
     } else {
       for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
     NameAnonymousBlocks(ifcmd.thn);
     if (ifcmd.elseBlock != null) {
       NameAnonymousBlocks(ifcmd.elseBlock);
     }
       }
     }
       }
 }
예제 #6
0
        void RecordSuccessors(StmtList stmtList, BigBlock successor)
        {
            Contract.Requires(stmtList != null);
              for (int i = stmtList.BigBlocks.Count; 0 <= --i; ) {
            BigBlock big = stmtList.BigBlocks[i];
            big.successorBigBlock = successor;

            if (big.ec is WhileCmd) {
              WhileCmd wcmd = (WhileCmd)big.ec;
              RecordSuccessors(wcmd.Body, successor);
            } else {
              for (IfCmd ifcmd = big.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
            RecordSuccessors(ifcmd.thn, successor);
            if (ifcmd.elseBlock != null) {
              RecordSuccessors(ifcmd.elseBlock, successor);
            }
              }
            }

            successor = big;
              }
        }
예제 #7
0
 private void ComputeAllLabels(StmtList stmts)
 {
     if (stmts == null) return;
       foreach (BigBlock bb in stmts.BigBlocks) {
     if (bb.LabelName != null) {
       allLabels.Add(bb.LabelName);
     }
     ComputeAllLabels(bb.ec);
       }
 }
예제 #8
0
        // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label;
        // otherwise, it is null.
        void CreateBlocks(StmtList stmtList, string runOffTheEndLabel)
        {
            Contract.Requires(stmtList != null);
              Contract.Requires(blocks != null);
              List<Cmd> cmdPrefixToApply = stmtList.PrefixCommands;

              int n = stmtList.BigBlocks.Count;
              foreach (BigBlock b in stmtList.BigBlocks) {
            n--;
            Contract.Assert(b.LabelName != null);
            List<Cmd> theSimpleCmds;
            if (cmdPrefixToApply == null) {
              theSimpleCmds = b.simpleCmds;
            } else {
              theSimpleCmds = new List<Cmd>();
              theSimpleCmds.AddRange(cmdPrefixToApply);
              theSimpleCmds.AddRange(b.simpleCmds);
              cmdPrefixToApply = null;  // now, we've used 'em up
            }

            if (b.tc != null) {
              // this BigBlock has the very same components as a Block
              Contract.Assert(b.ec == null);
              Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc);
              blocks.Add(block);

            } else if (b.ec == null) {
              TransferCmd trCmd;
              if (n == 0 && runOffTheEndLabel != null) {
            // goto the given label instead of the textual successor block
            trCmd = new GotoCmd(stmtList.EndCurly, new List<String> { runOffTheEndLabel });
              } else {
            trCmd = GotoSuccessor(stmtList.EndCurly, b);
              }
              Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd);
              blocks.Add(block);

            } else if (b.ec is BreakCmd) {
              BreakCmd bcmd = (BreakCmd)b.ec;
              Contract.Assert(bcmd.BreakEnclosure != null);
              Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure));
              blocks.Add(block);

            } else if (b.ec is WhileCmd) {
              WhileCmd wcmd = (WhileCmd)b.ec;
              string loopHeadLabel = prefix + anon + "_LoopHead";
              string/*!*/ loopBodyLabel = prefix + anon + "_LoopBody";
              string loopDoneLabel = prefix + anon + "_LoopDone";
              anon++;

              List<Cmd> ssBody = new List<Cmd>();
              List<Cmd> ssDone = new List<Cmd>();
              if (wcmd.Guard != null) {
            var ac = new AssumeCmd(wcmd.tok, wcmd.Guard);
            ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null);
            ssBody.Add(ac);

            ac = new AssumeCmd(wcmd.tok, Expr.Not(wcmd.Guard));
            ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null);
            ssDone.Add(ac);
              }

              // Try to squeeze in ssBody into the first block of wcmd.Body
              bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel);

              // ... goto LoopHead;
              Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new List<String> { loopHeadLabel }));
              blocks.Add(block);

              // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody;
              List<Cmd> ssHead = new List<Cmd>();
              foreach (PredicateCmd inv in wcmd.Invariants) {
            ssHead.Add(inv);
              }
              block = new Block(wcmd.tok, loopHeadLabel, ssHead, new GotoCmd(wcmd.tok, new List<String> { loopDoneLabel, loopBodyLabel }));
              blocks.Add(block);

              if (!bodyGuardTakenCareOf) {
            // LoopBody: assume guard; goto firstLoopBlock;
            block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new List<String> { wcmd.Body.BigBlocks[0].LabelName }));
            blocks.Add(block);
              }

              // recurse to create the blocks for the loop body
              CreateBlocks(wcmd.Body, loopHeadLabel);

              // LoopDone: assume !guard; goto loopSuccessor;
              TransferCmd trCmd;
              if (n == 0 && runOffTheEndLabel != null) {
            // goto the given label instead of the textual successor block
            trCmd = new GotoCmd(wcmd.tok, new List<String> { runOffTheEndLabel });
              } else {
            trCmd = GotoSuccessor(wcmd.tok, b);
              }
              block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd);
              blocks.Add(block);

            } else {
              IfCmd ifcmd = (IfCmd)b.ec;
              string predLabel = b.LabelName;
              List<Cmd> predCmds = theSimpleCmds;

              for (; ifcmd != null; ifcmd = ifcmd.elseIf) {
            string thenLabel = prefix + anon + "_Then";
            Contract.Assert(thenLabel != null);
            string elseLabel = prefix + anon + "_Else";
            Contract.Assert(elseLabel != null);
            anon++;

            List<Cmd> ssThen = new List<Cmd>();
            List<Cmd> ssElse = new List<Cmd>();
            if (ifcmd.Guard != null) {
              var ac = new AssumeCmd(ifcmd.tok, ifcmd.Guard);
              ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
              ssThen.Add(ac);

              ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard));
              ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
              ssElse.Add(ac);
            }

            // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock
            bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel);
            bool elseGuardTakenCareOf = false;
            if (ifcmd.elseBlock != null) {
              elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel);
            }

            // ... goto Then, Else;
            Block block = new Block(b.tok, predLabel, predCmds,
              new GotoCmd(ifcmd.tok, new List<String> { thenLabel, elseLabel }));
            blocks.Add(block);

            if (!thenGuardTakenCareOf) {
              // Then: assume guard; goto firstThenBlock;
              block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.thn.BigBlocks[0].LabelName }));
              blocks.Add(block);
            }

            // recurse to create the blocks for the then branch
            CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null);

            if (ifcmd.elseBlock != null) {
              Contract.Assert(ifcmd.elseIf == null);
              if (!elseGuardTakenCareOf) {
                // Else: assume !guard; goto firstElseBlock;
                block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.elseBlock.BigBlocks[0].LabelName }));
                blocks.Add(block);
              }

              // recurse to create the blocks for the else branch
              CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null);

            } else if (ifcmd.elseIf != null) {
              // this is an "else if"
              predLabel = elseLabel;
              predCmds = new List<Cmd>();
              if (ifcmd.Guard != null) {
                var ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard));
                ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null);
                predCmds.Add(ac);
              }

            } else {
              // no else alternative is specified, so else branch is just "skip"
              // Else: assume !guard; goto ifSuccessor;
              TransferCmd trCmd;
              if (n == 0 && runOffTheEndLabel != null) {
                // goto the given label instead of the textual successor block
                trCmd = new GotoCmd(ifcmd.tok, new List<String> { runOffTheEndLabel });
              } else {
                trCmd = GotoSuccessor(ifcmd.tok, b);
              }
              block = new Block(ifcmd.tok, elseLabel, ssElse, trCmd);
              blocks.Add(block);
            }
              }
            }
              }
        }
예제 #9
0
        void CheckLegalLabels(StmtList stmtList, StmtList parentContext, BigBlock parentBigBlock)
        {
            Contract.Requires(stmtList != null);
              Contract.Requires((parentContext == null) == (parentBigBlock == null));
              Contract.Requires(stmtList.ParentContext == null);  // it hasn't been set yet
              //modifies stmtList.*;
              Contract.Ensures(stmtList.ParentContext == parentContext);
              stmtList.ParentContext = parentContext;
              stmtList.ParentBigBlock = parentBigBlock;

              // record the labels declared in this StmtList
              foreach (BigBlock b in stmtList.BigBlocks) {
            if (b.LabelName != null) {
              string n = b.LabelName;
              if (n.StartsWith(prefix)) {
            if (prefix.Length < n.Length && n[prefix.Length] == '0') {
              prefix += "1";
            } else {
              prefix += "0";
            }
              }
              stmtList.Labels.Add(b.LabelName);
            }
              }

              // check that labels in this and nested StmtList's are legal
              foreach (BigBlock b in stmtList.BigBlocks) {
            // goto's must reference blocks in enclosing blocks
            if (b.tc is GotoCmd) {
              GotoCmd g = (GotoCmd)b.tc;
              foreach (string/*!*/ lbl in cce.NonNull(g.labelNames)) {
            Contract.Assert(lbl != null);
            /*
            bool found = false;
            for (StmtList sl = stmtList; sl != null; sl = sl.ParentContext) {
              if (sl.Labels.Contains(lbl)) {
                found = true;
                break;
              }
            }
            if (!found) {
              this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined or out of reach");
            }
            */
            if (!allLabels.Contains(lbl)) {
              this.errorHandler.SemErr(g.tok, "Error: goto label '" + lbl + "' is undefined");
            }
              }
            }

            // break labels must refer to an enclosing while statement
            else if (b.ec is BreakCmd) {
              BreakCmd bcmd = (BreakCmd)b.ec;
              Contract.Assert(bcmd.BreakEnclosure == null);  // it hasn't been initialized yet
              bool found = false;
              for (StmtList sl = stmtList; sl.ParentBigBlock != null; sl = sl.ParentContext) {
            cce.LoopInvariant(sl != null);
            BigBlock bb = sl.ParentBigBlock;

            if (bcmd.Label == null) {
              // a label-less break statement breaks out of the innermost enclosing while statement
              if (bb.ec is WhileCmd) {
                bcmd.BreakEnclosure = bb;
                found = true;
                break;
              }
            } else if (bcmd.Label == bb.LabelName) {
              // a break statement with a label can break out of both if statements and while statements
              if (bb.simpleCmds.Count == 0) {
                // this is a good target:  the label refers to the if/while statement
                bcmd.BreakEnclosure = bb;
              } else {
                // the label of bb refers to the first statement of bb, which in which case is a simple statement, not an if/while statement
                this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
              }
              found = true;  // don't look any further, since we've found a matching label
              break;
            }
              }
              if (!found) {
            if (bcmd.Label == null) {
              this.errorHandler.SemErr(bcmd.tok, "Error: break statement is not inside a loop");
            } else {
              this.errorHandler.SemErr(bcmd.tok, "Error: break label '" + bcmd.Label + "' must designate an enclosing statement");
            }
              }
            }

            // recurse
            else if (b.ec is WhileCmd) {
              WhileCmd wcmd = (WhileCmd)b.ec;
              CheckLegalLabels(wcmd.Body, stmtList, b);
            } else {
              for (IfCmd ifcmd = b.ec as IfCmd; ifcmd != null; ifcmd = ifcmd.elseIf) {
            CheckLegalLabels(ifcmd.thn, stmtList, b);
            if (ifcmd.elseBlock != null) {
              CheckLegalLabels(ifcmd.elseBlock, stmtList, b);
            }
              }
            }
              }
        }
예제 #10
0
 public BigBlocksResolutionContext(StmtList stmtList, Errors errorHandler)
 {
     Contract.Requires(errorHandler != null);
       Contract.Requires(stmtList != null);
       this.stmtList = stmtList;
       this.errorHandler = errorHandler;
       ComputeAllLabels(stmtList);
 }
예제 #11
0
 public WhileCmd(IToken tok, [Captured] Expr guard, List<PredicateCmd/*!*/>/*!*/ invariants, StmtList/*!*/ body)
     : base(tok)
 {
     Contract.Requires(cce.NonNullElements(invariants));
       Contract.Requires(body != null);
       Contract.Requires(tok != null);
       this.Guard = guard;
       this.Invariants = invariants;
       this.Body = body;
 }
예제 #12
0
 public IfCmd(IToken/*!*/ tok, Expr guard, StmtList/*!*/ thn, IfCmd elseIf, StmtList elseBlock)
     : base(tok)
 {
     Contract.Requires(tok != null);
       Contract.Requires(thn != null);
       Contract.Requires(elseIf == null || elseBlock == null);
       this.Guard = guard;
       this.thn = thn;
       this.elseIf = elseIf;
       this.elseBlock = elseBlock;
 }
예제 #13
0
 public Implementation(IToken/*!*/ tok,
   string/*!*/ name,
   List<TypeVariable>/*!*/ typeParams,
   List<Variable>/*!*/ inParams,
   List<Variable>/*!*/ outParams,
   List<Variable>/*!*/ localVariables,
   [Captured] StmtList/*!*/ structuredStmts,
   QKeyValue kv,
   Errors/*!*/ errorHandler)
   : base(tok, name, typeParams, inParams, outParams) {
   Contract.Requires(tok != null);
   Contract.Requires(name != null);
   Contract.Requires(typeParams != null);
   Contract.Requires(inParams != null);
   Contract.Requires(outParams != null);
   Contract.Requires(localVariables != null);
   Contract.Requires(structuredStmts != null);
   Contract.Requires(errorHandler != null);
   LocVars = localVariables;
   StructuredStmts = structuredStmts;
   BigBlocksResolutionContext ctx = new BigBlocksResolutionContext(structuredStmts, errorHandler);
   Blocks = ctx.Blocks;
   BlockPredecessorsComputed = false;
   scc = null;
   Attributes = kv;
 }