/// <summary>
 /// Constructor
 /// </summary>
 /// <param name="analyzer"></param>
 /// <param name="m"></param>
 public ReachingDefNNArrayInstructionVisitor(Analyzer analyzer, MethodReachingDefNNArrayChecker m) {
   this.analyzer = analyzer;
   checker = m;
   delayedParameters = DelayedParameters();
 }
    /// <summary>
    /// Standard check function, except that it returns a PreDAStatus data structure
    /// that contains the three tables mentioned above.
    /// </summary>
    /// <param name="t"></param>
    /// <param name="method"></param>
    /// <param name="analyzer"></param>
    /// <returns>A PreDAStatus data structure, or a null if error occurs. </returns>
    public static PreDAStatus Check(TypeSystem t, Method method, Analyzer analyzer) {
      Debug.Assert(method != null && analyzer != null);
      MethodReachingDefNNArrayChecker checker = new MethodReachingDefNNArrayChecker(t, analyzer, method);
      ControlFlowGraph cfg = analyzer.GetCFG(method);

      if (cfg == null)
        return null;

      InitializedVariables iv = new InitializedVariables(analyzer);
      NNArrayStatus status = new NNArrayStatus(iv);
      NNArrayStatus.Checker = checker;
      checker.Run(cfg, status);
      
      // Check whether there are arrays that have been created but not committed
      NNArrayStatus exitStatus2 = checker.exitState as NNArrayStatus;
      if (exitStatus2 != null) {
        if (Analyzer.Debug) {
          Console.WriteLine("exit state of {0} is", method.FullName);
          exitStatus2.Dump();
        }
        ArrayList notCommitted = exitStatus2.CreatedButNotInitedArrays();
        if (notCommitted != null && notCommitted.Count != 0) {
          foreach (object o in notCommitted) {
            string offendingString = "A non null element array";
            Node offendingNode = method;
            if (o is Variable) {
              offendingString = "Variable \'" + o + "\'";
              offendingNode = o as Variable;
            }
            if (o is Pair<Variable, Field>) {
              Pair<Variable, Field> pair = o as Pair<Variable, Field>;
              Variable var = pair.Fst;
              Field fld = pair.Snd;
              offendingString = "Field \'" + var + "." + fld + "\'";
              if (NNArrayStatus.FieldsToMB.ContainsKey(pair)) {
                offendingNode = NNArrayStatus.FieldsToMB[pair] as MemberBinding;
                if (offendingNode == null) {
                  offendingNode = fld;
                } else {
                  MemberBinding mb = offendingNode as MemberBinding;
                  if (mb.TargetObject == null || mb.SourceContext.SourceText == null) {
                    offendingNode = fld;
                  }
                }
              }
            }
            checker.HandleError(offendingNode, Error.ShouldCommit, offendingString);
          }
        }

        ArrayList notCommittedOnAllPaths = exitStatus2.CreatedButNotFullyCommittedArrays();
        if (notCommittedOnAllPaths != null && notCommittedOnAllPaths.Count != 0) {
          foreach (object o in notCommittedOnAllPaths) {
            string offendingString = "A non-null element array";
            Node offendingNode = method;
            if (o is Variable) {
              offendingString = "variable \'" + o + "\'";
              offendingNode = o as Variable;
            } else if (o is Pair<Variable, Field>) {
              Pair<Variable, Field> pair = o as Pair<Variable, Field>;
              Variable var = pair.Fst;
              Field fld = pair.Snd;
              if (NNArrayStatus.FieldsToMB.ContainsKey(pair)) {
                offendingNode = NNArrayStatus.FieldsToMB[pair] as MemberBinding;
                if (offendingNode == null) {
                  offendingNode = fld;
                } else {
                  MemberBinding mb = offendingNode as MemberBinding;
                  if (mb.TargetObject == null || mb.SourceContext.SourceText==null) {
                    offendingNode = fld;
                  }
                }
              }
              offendingString = "field \'" + var + "." + fld + "\'";
            }

            checker.HandleError(offendingNode, Error.ShouldCommitOnAllPaths, offendingString);
          }
        }
        if (checker.errors != null && checker.errors.Count != 0) {
          checker.HandleError();
          checker.errors.Clear();
          return null;
        }
      }
      return new PreDAStatus(checker.NotCommitted, checker.Committed, checker.OKTable, checker.NonDelayArrayTable);
    }