summaryrefslogtreecommitdiff
path: root/Source/AbsInt/LoopInvariantsOnDemand.cs
blob: 5bb5916d0c895190201e669b9b1bcd5cb29db673 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------
namespace Microsoft.Boogie.AbstractInterpretation {
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics.Contracts;
  using AI = Microsoft.AbstractInterpretationFramework;
  using Boogie = Microsoft.Boogie;



  /// <summary>
  /// A visitor of an abstract interpretation expression that collects the free variables 
  /// </summary>      
  class FreeVariablesVisitor : AI.ExprVisitor {
    [Peer]
    List<AI.IVariable> variables;
    [ContractInvariantMethod]
    void ObjectInvariant() {
      Contract.Invariant(cce.NonNullElements(variables));
      Contract.Invariant(cce.NonNullElements(varNames));
    }

    public List<AI.IVariable> FreeVariables {
      get {
        Contract.Ensures(cce.NonNullElements(Contract.Result<List<AI.IVariable>>()));

        return this.variables;
      }
    }

    List<string> varNames;    // used to check the consinstency!

    public FreeVariablesVisitor() {
      this.variables = new List<AI.IVariable>();
      this.varNames = new List<string>();
    }

    override public object Default(AI.IExpr expr) {
      Contract.Requires(expr != null);
      if (expr is AI.IVariable) {
        if (!variables.Contains((AI.IVariable)expr)) {
          this.variables.Add((AI.IVariable)expr);

          Contract.Assert(!this.varNames.Contains(expr.ToString()));     // If we get there, we have an error: two variables with the same name but different identity  

          this.varNames.Add(expr.ToString());
        }
        return null;
      } else if (expr is AI.IFunApp)
        return VisitFunApp((AI.IFunApp)expr);
      else if (expr is AI.IFunction)
        return VisitFunction((AI.IFunction)expr);
      else if (expr is AI.IUnknown)
        return null;
      else {
        Contract.Assert(false);
        throw new cce.UnreachableException();
      }
    }

    public override object VisitFunApp(AI.IFunApp funapp) {
      Contract.Requires(funapp != null);
      foreach (AI.IExpr arg in funapp.Arguments) {
        Contract.Assert(arg != null);
        arg.DoVisit(this);
      }
      return true;
    }

    public override object VisitFunction(AI.IFunction fun) {
      Contract.Requires(fun != null);
      fun.Body.DoVisit(this);
      this.variables.Remove(fun.Param);
      return true;
    }

  }

}