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