public override Element/*!*/ NontrivialMeet(Element/*!*/ first, Element/*!*/ second) {
      //Contract.Requires(second != null);
      //Contract.Requires(first != null);
      Contract.Ensures(Contract.Result<Element>() != null);
      Elt a = (Elt)first;
      Elt b = (Elt)second;
      Contract.Assert(a.what != What.Bottom && b.what != What.Bottom);

      if (a.what == What.Exact && b.what == What.Exact) {
        Contract.Assert(a.ty != null && b.ty != null);
        if (factory.IsTypeEqual(a.ty, b.ty)) {
          return a;
        } else {
          return Bottom;
        }

      } else if (a.what == What.Exact || b.what == What.Exact) {
        // One is Bounds, the other Exact.  Make b be the Bounds one.
        if (a.what == What.Bounds) {
          Elt tmp = a;
          a = b;
          b = tmp;
        }
        Contract.Assert(a.what == What.Exact && b.what == What.Bounds);
        // Check the exact type against all bounds.  If the exact type is more restrictive
        // than all bounds, then return it.  If some bound is not met by the exact type, return
        // bottom.
        Contract.Assert(a.ty != null);
        if (b.ty != null && !factory.IsSubType(a.ty, b.ty)) {
          return Bottom;
        }
        if (b.manyBounds != null) {
          foreach (IExpr/*!*/ bound in b.manyBounds) {
            Contract.Assert(bound != null);
            if (!factory.IsSubType(a.ty, bound)) {
              return Bottom;
            }
          }
        }
        return a;
      } else {
        // Both operands are Bounds.
        Contract.Assert(a.what == What.Bounds && b.what == What.Bounds);

        // Take all the bounds, but prune those bounds that follow from others.
        Contract.Assert(1 <= a.BoundsCount && 1 <= b.BoundsCount);  // a preconditions is that neither operand is Top
        int n = a.BoundsCount + b.BoundsCount;
        // Special case:  a and b each has exactly one bound
        if (n == 2) {
          Contract.Assert(a.ty != null && b.ty != null);
          if (factory.IsSubType(a.ty, b.ty)) {
            // a is more restrictive
            return a;
          } else if (factory.IsSubType(b.ty, a.ty)) {
            // b is more restrictive
            return b;
          } else {
            IExpr[]/*!*/ bounds = new IExpr[2];
            bounds[0] = a.ty;
            bounds[1] = b.ty;
            return new Elt(bounds);
          }
        }

        // General case
        ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n);
        if (a.ty != null) {
          allBounds.Add(a.ty);
        } else {
          allBounds.AddRange(cce.NonNull(a.manyBounds));
        }
        int bStart = allBounds.Count;
        if (b.ty != null) {
          allBounds.Add(b.ty);
        } else {
          allBounds.AddRange(cce.NonNull(b.manyBounds));
        }
        for (int i = 0; i < bStart; i++) {
          IExpr/*!*/ aBound = cce.NonNull((IExpr)allBounds[i]);
          for (int j = bStart; j < allBounds.Count; j++) {
            IExpr bBound = (IExpr/*! Wouldn't the non-null typing in the original Spec# code had made bBound never null, 
                                              * thus negating the need for the continue statement?*/
                                                                                        )allBounds[j];
            if (bBound == null) {
              continue;
            } else if (factory.IsSubType(aBound, bBound)) {
              // a is more restrictive, so blot out the b bound
              allBounds[j] = null;
              n--;
            } else if (factory.IsSubType(bBound, aBound)) {
              // b is more restrictive, so blot out the a bound
              allBounds[i] = null;
              n--;
              goto CONTINUE_OUTER_LOOP;
            }
          }
        CONTINUE_OUTER_LOOP: {
          }
        }
        Contract.Assert(1 <= n);
        return new Elt(allBounds, n);
      }
    }
Example #2
0
        public override Element /*!*/ NontrivialMeet(Element /*!*/ first, Element /*!*/ second)
        {
            //Contract.Requires(second != null);
            //Contract.Requires(first != null);
            Contract.Ensures(Contract.Result <Element>() != null);
            Elt a = (Elt)first;
            Elt b = (Elt)second;

            Contract.Assert(a.what != What.Bottom && b.what != What.Bottom);

            if (a.what == What.Exact && b.what == What.Exact)
            {
                Contract.Assert(a.ty != null && b.ty != null);
                if (factory.IsTypeEqual(a.ty, b.ty))
                {
                    return(a);
                }
                else
                {
                    return(Bottom);
                }
            }
            else if (a.what == What.Exact || b.what == What.Exact)
            {
                // One is Bounds, the other Exact.  Make b be the Bounds one.
                if (a.what == What.Bounds)
                {
                    Elt tmp = a;
                    a = b;
                    b = tmp;
                }
                Contract.Assert(a.what == What.Exact && b.what == What.Bounds);
                // Check the exact type against all bounds.  If the exact type is more restrictive
                // than all bounds, then return it.  If some bound is not met by the exact type, return
                // bottom.
                Contract.Assert(a.ty != null);
                if (b.ty != null && !factory.IsSubType(a.ty, b.ty))
                {
                    return(Bottom);
                }
                if (b.manyBounds != null)
                {
                    foreach (IExpr /*!*/ bound in b.manyBounds)
                    {
                        Contract.Assert(bound != null);
                        if (!factory.IsSubType(a.ty, bound))
                        {
                            return(Bottom);
                        }
                    }
                }
                return(a);
            }
            else
            {
                // Both operands are Bounds.
                Contract.Assert(a.what == What.Bounds && b.what == What.Bounds);

                // Take all the bounds, but prune those bounds that follow from others.
                Contract.Assert(1 <= a.BoundsCount && 1 <= b.BoundsCount); // a preconditions is that neither operand is Top
                int n = a.BoundsCount + b.BoundsCount;
                // Special case:  a and b each has exactly one bound
                if (n == 2)
                {
                    Contract.Assert(a.ty != null && b.ty != null);
                    if (factory.IsSubType(a.ty, b.ty))
                    {
                        // a is more restrictive
                        return(a);
                    }
                    else if (factory.IsSubType(b.ty, a.ty))
                    {
                        // b is more restrictive
                        return(b);
                    }
                    else
                    {
                        IExpr[] /*!*/ bounds = new IExpr[2];
                        bounds[0] = a.ty;
                        bounds[1] = b.ty;
                        return(new Elt(bounds));
                    }
                }

                // General case
                ArrayList /*IExpr*/ allBounds = new ArrayList/*IExpr*/ (n);
                if (a.ty != null)
                {
                    allBounds.Add(a.ty);
                }
                else
                {
                    allBounds.AddRange(cce.NonNull(a.manyBounds));
                }
                int bStart = allBounds.Count;
                if (b.ty != null)
                {
                    allBounds.Add(b.ty);
                }
                else
                {
                    allBounds.AddRange(cce.NonNull(b.manyBounds));
                }
                for (int i = 0; i < bStart; i++)
                {
                    IExpr /*!*/ aBound = cce.NonNull((IExpr)allBounds[i]);
                    for (int j = bStart; j < allBounds.Count; j++)
                    {
                        IExpr bBound = (IExpr/*! Wouldn't the non-null typing in the original Spec# code had made bBound never null,
                                              * thus negating the need for the continue statement?*/
                                        )allBounds[j];
                        if (bBound == null)
                        {
                            continue;
                        }
                        else if (factory.IsSubType(aBound, bBound))
                        {
                            // a is more restrictive, so blot out the b bound
                            allBounds[j] = null;
                            n--;
                        }
                        else if (factory.IsSubType(bBound, aBound))
                        {
                            // b is more restrictive, so blot out the a bound
                            allBounds[i] = null;
                            n--;
                            goto CONTINUE_OUTER_LOOP;
                        }
                    }
                    CONTINUE_OUTER_LOOP : {
                    }
                }
                Contract.Assert(1 <= n);
                return(new Elt(allBounds, n));
            }
        }
    public override Element/*!*/ NontrivialJoin(Element/*!*/ first, Element/*!*/ second) {
      //Contract.Requires(second != null);
      //Contract.Requires(first != null);
      Contract.Ensures(Contract.Result<Element>() != null);
      Elt a = (Elt)first;
      Elt b = (Elt)second;
      Contract.Assert(a.what != What.Bottom && b.what != What.Bottom);
      if (a.what == What.Exact && b.what == What.Exact) {
        Contract.Assert(a.ty != null && b.ty != null);
        if (factory.IsTypeEqual(a.ty, b.ty)) {
          return a;
        } else {
          return new Elt(What.Bounds, factory.JoinTypes(a.ty, b.ty));
        }
      }

      // The result is going to be a Bounds, since at least one of the operands is a Bounds.
      Contract.Assert(1 <= a.BoundsCount && 1 <= b.BoundsCount);  // a preconditions is that neither operand is Top
      int n = a.BoundsCount + b.BoundsCount;

      // Special case:  a and b each has exactly one bound
      if (n == 2) {
        Contract.Assert(a.ty != null && b.ty != null);
        IExpr join = factory.JoinTypes(a.ty, b.ty);
        Contract.Assert(join != null);
        if (join == a.ty && a.what == What.Bounds) {
          return a;
        } else if (join == b.ty && b.what == What.Bounds) {
          return b;
        } else {
          return new Elt(What.Bounds, join);
        }
      }

      // General case
      ArrayList /*IExpr*/ allBounds = new ArrayList /*IExpr*/ (n);  // final size
      ArrayList /*IExpr!*/ result = new ArrayList /*IExpr!*/ (n);  // a guess at the size, but could be as big as size(a)*size(b)
      if (a.ty != null) {
        allBounds.Add(a.ty);
      } else {
        allBounds.AddRange(cce.NonNull(a.manyBounds));
      }
      int bStart = allBounds.Count;
      if (b.ty != null) {
        allBounds.Add(b.ty);
      } else {
        allBounds.AddRange(cce.NonNull(b.manyBounds));
      }
      // compute the join of each pair, putting non-redundant joins into "result"
      for (int i = 0; i < bStart; i++) {
        IExpr/*!*/ aBound = cce.NonNull((IExpr/*!*/)allBounds[i]);
        for (int j = bStart; j < allBounds.Count; j++) {
          IExpr/*!*/ bBound = (IExpr/*!*/)cce.NonNull(allBounds[j]);

          IExpr/*!*/ join = factory.JoinTypes(aBound, bBound);
          Contract.Assert(join != null);

          int k = 0;
          while (k < result.Count) {
            IExpr/*!*/ r = (IExpr/*!*/)cce.NonNull(result[k]);
            if (factory.IsSubType(join, r)) {
              // "join" is more restrictive than a bound already placed in "result",
              // so toss out "join" and compute the join of the next pair
              goto NEXT_PAIR;
            } else if (factory.IsSubType(r, join)) {
              // "join" is less restrictive than a bound already placed in "result",
              // so toss out that old bound
              result.RemoveAt(k);
            } else {
              k++;
            }
          }
          result.Add(join);
        NEXT_PAIR: {
          }
        }
      }
      return new Elt(result, result.Count);
    }
Example #4
0
        public override Element /*!*/ NontrivialJoin(Element /*!*/ first, Element /*!*/ second)
        {
            //Contract.Requires(second != null);
            //Contract.Requires(first != null);
            Contract.Ensures(Contract.Result <Element>() != null);
            Elt a = (Elt)first;
            Elt b = (Elt)second;

            Contract.Assert(a.what != What.Bottom && b.what != What.Bottom);
            if (a.what == What.Exact && b.what == What.Exact)
            {
                Contract.Assert(a.ty != null && b.ty != null);
                if (factory.IsTypeEqual(a.ty, b.ty))
                {
                    return(a);
                }
                else
                {
                    return(new Elt(What.Bounds, factory.JoinTypes(a.ty, b.ty)));
                }
            }

            // The result is going to be a Bounds, since at least one of the operands is a Bounds.
            Contract.Assert(1 <= a.BoundsCount && 1 <= b.BoundsCount); // a preconditions is that neither operand is Top
            int n = a.BoundsCount + b.BoundsCount;

            // Special case:  a and b each has exactly one bound
            if (n == 2)
            {
                Contract.Assert(a.ty != null && b.ty != null);
                IExpr join = factory.JoinTypes(a.ty, b.ty);
                Contract.Assert(join != null);
                if (join == a.ty && a.what == What.Bounds)
                {
                    return(a);
                }
                else if (join == b.ty && b.what == What.Bounds)
                {
                    return(b);
                }
                else
                {
                    return(new Elt(What.Bounds, join));
                }
            }

            // General case
            ArrayList /*IExpr*/  allBounds = new ArrayList/*IExpr*/ (n);  // final size
            ArrayList /*IExpr!*/ result    = new ArrayList/*IExpr!*/ (n); // a guess at the size, but could be as big as size(a)*size(b)

            if (a.ty != null)
            {
                allBounds.Add(a.ty);
            }
            else
            {
                allBounds.AddRange(cce.NonNull(a.manyBounds));
            }
            int bStart = allBounds.Count;

            if (b.ty != null)
            {
                allBounds.Add(b.ty);
            }
            else
            {
                allBounds.AddRange(cce.NonNull(b.manyBounds));
            }
            // compute the join of each pair, putting non-redundant joins into "result"
            for (int i = 0; i < bStart; i++)
            {
                IExpr /*!*/ aBound = cce.NonNull((IExpr /*!*/)allBounds[i]);
                for (int j = bStart; j < allBounds.Count; j++)
                {
                    IExpr /*!*/ bBound = (IExpr /*!*/)cce.NonNull(allBounds[j]);

                    IExpr /*!*/ join = factory.JoinTypes(aBound, bBound);
                    Contract.Assert(join != null);

                    int k = 0;
                    while (k < result.Count)
                    {
                        IExpr /*!*/ r = (IExpr /*!*/)cce.NonNull(result[k]);
                        if (factory.IsSubType(join, r))
                        {
                            // "join" is more restrictive than a bound already placed in "result",
                            // so toss out "join" and compute the join of the next pair
                            goto NEXT_PAIR;
                        }
                        else if (factory.IsSubType(r, join))
                        {
                            // "join" is less restrictive than a bound already placed in "result",
                            // so toss out that old bound
                            result.RemoveAt(k);
                        }
                        else
                        {
                            k++;
                        }
                    }
                    result.Add(join);
                    NEXT_PAIR : {
                    }
                }
            }
            return(new Elt(result, result.Count));
        }