private void CheckReturnNotDelay(InitializedVariables iv, Variable var, Node context) {
   if (var == null)
     return;
   if (!iv.CanAssumeNotDelayed(var) && !this.mpc.currentMethod.IsPropertyGetter) {
     if (!mpc.reportedErrors.Contains(var) && var.Name != null && var.Name.Name != "") {
       Error errorCode = Error.ReturnOfDelayedValue;
       Node offendingNode = (var.SourceContext.Document == null) ? context : var;
       mpc.typeSystem.HandleError(offendingNode, errorCode, var.Name.Name);
       mpc.reportedErrors.Add(var, null);
     }
   }
   iv.SetValueNonDelayed(var);
 }
    /// <summary>
    /// The instantiated formal type is non-delayed unless the parameter is marked delayed and "delayedInstance" is true.
    /// [Existential Delay Change] When there is only one delayed argument, we allow it to be existential delayed
    /// This is done by keeping track of the number of possible delay matches. 
    /// if actual/formal is universal/universal, then this number (possibleDelayMatch) is not changed, we allow it only when
    ///      the number is not zero (the only way it can be zero at this point (delayinstance is true) is because
    ///      an existential/universal delay match happened.
    /// if actual/formal is existential/universal, then match happens only when the number is 1
    ///      number is changed to zero to disallow future existential/universal match
    /// Delay match error will be reported as delay not compatible with the witness. If the witness does not have an appropriate delay
    /// we do not report an error, which will be safe (see comments below).
    /// </summary>
    private void CheckParameterDelay(InitializedVariables iv, Variable actual, Method callee, Parameter p, 
      bool delayedInstance, Node context,
      int witness, int num) {
      if (actual == null) return;
      if (p == null) return;

      // Special check that we don't pass pointers to delayed objects by reference
      Reference r = p.Type as Reference;
      if (r != null && !r.ElementType.IsValueType) {
        if (iv.IsDelayed(actual) || iv.IsDelayedRefContents(actual)) {
          Node offendingNode = (actual.SourceContext.Document != null) ? actual : context;
          mpc.typeSystem.HandleError(offendingNode, Error.DelayedReferenceByReference);
          return;
        }
      }

      // delayed instance requires that for every delayed formal, the corresponding actual must
      // be committed to an appropriate delay type. 
      if (delayedInstance && this.IsUniversallyDelayed(p)) {
        // CanAssumeDelay Decides whether the actual 1) is of the same delay (universal delay) as the formal
        //                                        or 2) is bottom, thus can be assumed to be universal delay afterwards
        // CanAssumeDelay cannot decide, and thus returns false when actual is existentially delayed
        bool actualIsSameDelayAsFormal = iv.CanAssumeDelayed(actual);

        if (actualIsSameDelayAsFormal) { 
          return;
        }

        if (iv.IsExistentialDelayed(actual))
        {
          // errors, if any, has been handled already in MethodCallDelayInstance
          // return here to avoid falling into the error reporting below. 
          return;
        }

        // if p is a universally delayed parameter, while actual cannot take a delayed type, 
        // (e.g., it is top), report error
        Node offendingNode = (actual.SourceContext.Document != null) ? actual : context;
        if (p is This) {
          mpc.typeSystem.HandleError(offendingNode, Error.ReceiverMustBeDelayed);
        }
        else {
          if (num != witness) // note this is not an extra check, the fact that witness is the position of the
            // first known delayed actual doesnt mean it will match correctly (i.e., possibly delay match might
            // not be right. 
            // We are not losing warnings either because if num == witness, only if possiblyDelayMatch == 1
            // we will have no warning, in which case, we are guaranteed to have a delay match and won't reach here
          {
            mpc.typeSystem.HandleError(offendingNode, Error.ActualMustBeDelayed, num.ToString(), (witness==0)?"this(receiver)": "No."+witness.ToString());
          }
        }
        return;
      }
      else {
        /* 
        if (callee is InstanceInitializer && p is This && iv.IsBottom(actual)) {
          if (ThisIsSoleDelayedParameter(callee)) {
            // leave undetermined status of this.
            return;
          }
        }
        */
        // actual is known to be not delayed. CanAssumeNotDelay has this side effect to change
        // actual's delay type from bottom to nondelay if its type is not already nondelay
        if (iv.CanAssumeNotDelayed(actual)) {
          return;
        }
        // if its type is delayed, or top, report error... it is assumed that actual's type cannot 
        // be top, which, when violated (likely to happen), leads to inaccurate error message.
        // TODO: distinguish between actual's type being delayed or being top.
        Node offendingNode = (actual.SourceContext.Document != null) ? actual : context;
        if (p is This) {
        //  System.Console.WriteLine("p is Universally delayed: {0}", this.IsUniversallyDelayed(p));
        //  System.Console.WriteLine("delayInstance is {0}", delayedInstance);
        //  System.Console.WriteLine("{0} violates delay of {1}", actual, p);
        //  System.Console.WriteLine("Value of possible delay match:{0} ", possibleDelayMatch);
          mpc.typeSystem.HandleError(offendingNode, Error.ReceiverCannotBeDelayed);
        }
        else {
          //System.Console.WriteLine("{0} is offending {1} for function {2}", actual, p, callee.Name);
          //System.Console.WriteLine("delayinstance:{0}; possibleDelayMatch:{1}", delayedInstance, possibleDelayMatch);
          //iv.PrintStatus(actual);
          //System.Console.WriteLine("p is universally delayed: {0}", this.IsUniversallyDelayed(p));
          mpc.typeSystem.HandleError(offendingNode, Error.ActualCannotBeDelayed);
        }
        return;
      }
    }
 private void CheckNonDelay(InitializedVariables iv, Variable var, Node context, Error errorCode) {
   if (var == null)
     return;
   if (!iv.CanAssumeNotDelayed(var)) {
     if (!mpc.reportedErrors.Contains(var) && var.Name != null && var.Name.Name != "") {
       // Ugly hack to get delayed analysis past non-conformant use of get_FrameGuard.
       if (!(mpc.currentMethod.Name != null && mpc.currentMethod.Name.Name.StartsWith("get_SpecSharp::FrameGuard"))) {
         Node offendingNode = (var.SourceContext.Document == null) ? context : var;
         mpc.typeSystem.HandleError(offendingNode, errorCode, var.Name.Name);
         mpc.reportedErrors.Add(var, null);
       }
     }
   }
   iv.SetValueNonDelayed(var);
 }