public void CheckArguments(Variable [] args, NNArrayStatus status) {
   if (args == null) return;
   foreach (Variable v in args) {
       CheckVariable(v, status);
   }
 }
    /// <summary>
    /// See if the value of this v is the same as the set of delayed Parameters.
    /// If so, set the status to be true;
    /// </summary>
    /// <param name="v"></param>
    public void CheckVariable(Variable v, NNArrayStatus status) {

      if (v == null) return;

      if (isNNArrayType(v.Type)) {
        if (status.ContainsValueAtTop(v)) {
          // do nothing
        }
        else {
          status.CrushStackToLevelContaining(v);
        }
      }
      //foreach (Parameter p in delayedParameters) {
      //  if (isSameVar(p,v) || status.HasSameValue(p, v)) {
      //    status.SetEscaped(); 
      //  }
      //}
    }
 public void CheckArguments(ExpressionList args, NNArrayStatus status) {
   if (args == null) return;
   foreach (Expression e in args) {
     Variable v = e as Variable;
     if (v != null) {
       CheckVariable(v, status);
     }
   }
 }
    /// <summary>
    /// TODO: The set of vars/fields that are created only/committed must agree
    /// </summary>
    /// <returns></returns>
    public static NNArrayStatus Merge(NNArrayStatus atMerge, NNArrayStatus incoming, CfgBlock joinPoint) {
      Debug.Assert(atMerge != null && incoming != null);   
      // if (atMerge == incoming) return null;
      InitializedVariables result = InitializedVariables.Merge(atMerge.ivs, incoming.ivs, joinPoint);
      if (result == null
        && atMerge.vars.Equals(incoming.vars)
        && atMerge.fields.Equals(incoming.fields)
        && atMerge.zeroInts.Equals(incoming.zeroInts)
        ) 
        return null;

      if (result == null) result = atMerge.ivs; 

      return new NNArrayStatus(result, (HashSet)Set.Union(atMerge.vars, incoming.vars),  
        Set.Union(atMerge.fields,incoming.fields) as HashSet, 
        Set.Intersect(atMerge.zeroInts, incoming.zeroInts) as HashSet,
        mergeStack(atMerge.stack, incoming.stack, result));
    }
 public static bool CanBeNondelayed(NNArrayStatus status) {
   if (status == null) return false;
   int rs = status.NumOfCreatedButNotInitedArrays();
   return (rs == 1); // has only one delayed arrays.
 }
 public NNArrayStatus(NNArrayStatus nnas) {
   this.ivs = new InitializedVariables(nnas.ivs);
   this.vars = nnas.vars;
   this.fields = nnas.fields;
   this.zeroInts = nnas.zeroInts;
   stack = new InitializedVarStack(nnas.stack);
 }
    protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState state) {
      Debug.Assert(block != null);

      NNArrayStatus onEntry = (NNArrayStatus)state;
      currBlock = block;

      if (Analyzer.Debug) {
        Analyzer.Write("---------block: " + block.UniqueId + ";");
        Analyzer.Write("   Exit:");
        foreach (CfgBlock b in block.NormalSuccessors)
          Analyzer.Write(b.UniqueId + ";");
        if (block.UniqueSuccessor != null)
          Analyzer.Write("   FallThrough: " + block.UniqueSuccessor + ";");
        if (block.ExceptionHandler != null)
          Analyzer.Write("   ExHandler: " + block.ExceptionHandler.UniqueId + ";");
        Analyzer.WriteLine("");
        state.Dump();
      }
      if (block.ExceptionHandler != null) {
        NNArrayStatus exnState = onEntry;
        onEntry = new NNArrayStatus(onEntry); // Copy state, since common ancestor cannot be modified any longer
        PushExceptionState(block, exnState);
      }

      NNArrayStatus resultState = (NNArrayStatus)base.VisitBlock(block, onEntry);
      if (block.UniqueId == cfg.NormalExit.UniqueId) {
        exitState = resultState;
      }
      if (resultState == null) {
        return null;
      }
      return new NNArrayStatus(resultState);

    }
    /// <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);
    }