예제 #1
0
 /// <summary>
 /// requires serFor is Method || serFor is ModelfieldContract
 /// if serFor is a ModelfieldContract mfC, then mfC.Witness is serialized as well.
 /// </summary>        
 protected virtual void SerializeWUCs(WUCs toSerialize, Node serializeFor) {      
   ModelfieldContract mfC = serializeFor as ModelfieldContract;
   if (mfC != null && mfC.Witness != null)
     toSerialize.Exact.Add(new WitnessUnderConstruction(mfC.Witness, null, 0)); //add user-defined witness (optimization: make it the first witness)
   bool isUpper = false;
   this.SerializeWUCList(toSerialize.Exact, isUpper, serializeFor);
   this.SerializeWUCList(toSerialize.Lowerbounds, isUpper, serializeFor);
   isUpper = true;
   this.SerializeWUCList(toSerialize.Upperbounds, isUpper, serializeFor);
 }
예제 #2
0
    /// <param name="e">the expression for which we are trying to find possible witnesses of consistency</param>
    /// <param name="modelfield">the modelfield for which we are trying to find a witness, or null if we are looking for result in a method postcondition</param>
    /// <param name="witnessType">the type of the witness we are looking for</param>    
    protected static WUCs GetWUCs(Expression e, Member modelfield, TypeNode witnessType) {
      WUCs result = new WUCs();
      BinaryExpression be = e as BinaryExpression;
      TernaryExpression te = e as TernaryExpression;

      NodeType nt = e.NodeType;
      if (nt == NodeType.Eq || nt == NodeType.Iff || nt == NodeType.Ge || nt == NodeType.Gt
        || nt == NodeType.Le || nt == NodeType.Lt || nt == NodeType.Ne) {
        #region don't want to go into either operand, but check if either operand is a witness candidate.
        Expression inferredWitness = Checker.GetWitnessHelper(e, modelfield); //theModelField == null means we are looking for result in method postcondition
        if (inferredWitness != null) {
          WitnessUnderConstruction wuc = new WitnessUnderConstruction(inferredWitness, null, 0);
          if (nt == NodeType.Eq || nt == NodeType.Iff)
            result.Exact.Add(wuc); //found result <==> P. Then P is the only potential witness.            
          else {
            //When we find one of the numeric operators, we can assume that witnessType is numeric,
            //as otherwise the type checker will have produced an error.
            if (nt == NodeType.Ge)
              result.Lowerbounds.Add(wuc);
            else if (nt == NodeType.Gt) {
              wuc.Witness = new BinaryExpression(inferredWitness, new Literal(1, witnessType), NodeType.Add, witnessType, inferredWitness.SourceContext); //witness = witness + 1
              result.Lowerbounds.Add(wuc);
            } else if (nt == NodeType.Le)
              result.Upperbounds.Add(wuc);
            else if (nt == NodeType.Lt) {
              wuc.Witness = new BinaryExpression(inferredWitness, new Literal(1, witnessType), NodeType.Sub, witnessType, inferredWitness.SourceContext); //witness = witness - 1
              result.Upperbounds.Add(wuc);
            } else if (nt == NodeType.Ne)
              result.Neqs.Add(wuc);
          }
        }
        #endregion
      } else if (nt == NodeType.LogicalAnd || nt == NodeType.LogicalOr || nt == NodeType.And || nt == NodeType.Or) {
        #region go into both operands and combine results based on nt
        WUCs lhsWUCs = GetWUCs(be.Operand1, modelfield, witnessType);
        WUCs rhsWUCs = GetWUCs(be.Operand2, modelfield, witnessType);

        if (nt == NodeType.And || nt == NodeType.LogicalAnd) {
          //Todo: Optimization - if lhsWUCs only contains exact witnesses, we can ignore whatever witnesses came from rhsWUCs (but deal with rhsNeq's).
          //we can also take max of all lowerbounds and discard others
          //Reconsider these optimizations: do they work for !(P)?

          //Increase the nr of duplications in non-exact lhsWUCs elements by rhsWUCs.Neqs.Length (and vice versa).
          lhsWUCs.Duplicate(rhsWUCs.Neqs.Count);
          rhsWUCs.Duplicate(lhsWUCs.Neqs.Count);
          //It might be that the right-hand side witnesses are total only given the validity of the be.Operand1.
          //Therefore, we want to guard these witnesses by be.Operand1. However, if be.Operand1 contains the modelfield/result value, 
          //that trick is not going to work: it needs to be evaluated with the witness as its value.
          //i.e., if the witness is only total when be.operand1 holds, then it is not a good witness when be.operand1 requires its evaluation.
          if (nt == NodeType.LogicalAnd && lhsWUCs.IsEmpty)
            rhsWUCs.Guard(be.Operand1);
        } else if (nt == NodeType.LogicalOr) {
          //No need to increase duplicates for || (or |). But we can guard the rhs by !(lhs) if lhs doesn't give witnesses. 
          if (lhsWUCs.IsEmpty)
            rhsWUCs.Guard(new UnaryExpression(be.Operand1, NodeType.Neg, SystemTypes.Boolean));
        }
        result.Add(lhsWUCs);
        result.Add(rhsWUCs);
        #endregion
      } else if (nt == NodeType.Implies) {
        #region Treat A ==> B as !A || B
        Expression notA = new UnaryExpression(be.Operand1, NodeType.Neg, SystemTypes.Boolean);
        Expression notAorB = new BinaryExpression(notA, be.Operand2, NodeType.Or, SystemTypes.Boolean);
        result = GetWUCs(notAorB, modelfield, witnessType);
        #endregion
      } else if (te != null) {
        #region Treat P ? A : B as P ==> A && !P ==> B
        //Need to look into P for witnesses to: for instance, consider the consistent contract ensures result == 5 ? true : false;
        //But also want to pick up witnesses from !P: for instance, consider the consistent contract ensures !(result == 5 ? false : true);
        //In the second case it is essential to have 5 in result.neq so that ! can turn it into an exact witness. 
        Expression PimplA = new BinaryExpression(te.Operand1, te.Operand2, NodeType.Implies);
        Expression notP = new UnaryExpression(te.Operand1, NodeType.Neg, SystemTypes.Boolean);
        Expression notPimplB = new BinaryExpression(notP, te.Operand3, NodeType.Implies);
        Expression and = new BinaryExpression(PimplA, notPimplB, NodeType.And);
        return GetWUCs(and, modelfield, witnessType);
        #endregion
      } else if (nt == NodeType.Neg) {
        #region Treat !(A) by flipping all the results we get from A
        WUCs wucs = GetWUCs((e as UnaryExpression).Operand, modelfield, witnessType);
        result.Exact = wucs.Neqs;
        result.Upperbounds = wucs.Lowerbounds; //Example: !(result > 4). Then we get a lowerbound of 5 in wucs. We need to turn that into an upperbound of 4.
        AddOrSub(result.Upperbounds, 1, NodeType.Add);
        result.Lowerbounds = wucs.Upperbounds;
        AddOrSub(result.Lowerbounds, 1, NodeType.Sub);
        result.Neqs = wucs.Exact;
        #endregion
      }
      return result;
    }
예제 #3
0
 public void Add(WUCs wuscToAdd) {
   this.Exact.AddRange(wuscToAdd.Exact);
   this.Upperbounds.AddRange(wuscToAdd.Upperbounds);
   this.Lowerbounds.AddRange(wuscToAdd.Lowerbounds);
   this.Neqs.AddRange(wuscToAdd.Neqs);
 }
예제 #4
0
 protected static WUCs GetWitnesses(Expression e, Member modelfield, TypeNode/*!*/ witnessType) {
   Debug.Assert(witnessType != null);      
   WUCs result = new WUCs();
   if (witnessType == SystemTypes.Boolean) {
     //enumerate over all possible witness: i.e, true and false
     result.Exact.Add(new WitnessUnderConstruction(new Literal(true, SystemTypes.Boolean), null, 0));
     result.Exact.Add(new WitnessUnderConstruction(new Literal(false, SystemTypes.Boolean), null, 0));
   } else if (witnessType.NodeType == NodeType.EnumNode) {
     //enumerate over all possible witnesses: i.e., the members of the enum          
     for (int i = 0; i < witnessType.Members.Count; i++ )
       result.Exact.Add(new WitnessUnderConstruction(new Literal(i, witnessType), null, 0));
   } else {        
     //search for witnesses in expression e
     if (e != null)
       result = Checker.GetWUCs(e, modelfield, witnessType);
     if (result.Exact.Count > 0)
       result.RuntimeWitness = result.Exact[0].Witness;  //pick one of the exact witnesses as the runtime witness
     //Now need to add the default witness(es) to the mix. 
     //Toss in (WUC.Neqs.Count + 1) defaultWitnesses (note that the nr of duplicates is not useful unless witnessType is numeric, but ok).
     //doesn't really matter if we treat the default as exact, upper or lower bound as it is only aiming at branches that contain no witnesses.
     foreach (Expression defaultWitness in Checker.GetDefaultWitnesses(witnessType))
       result.Exact.Add(new WitnessUnderConstruction(defaultWitness, null, result.Neqs.Count));            
     #region reverse the order of the Exact witnesses
     //want to add defaults as the first elements, as the default witness will not give an exception -> add to exact. Note that that might break the 
     //invariant that exact-elements have NrOfDuplicates == 0.
     List<WitnessUnderConstruction> exactWithDefault = new List<WitnessUnderConstruction>();      
     for (int i = 0; i < result.Exact.Count; i++)
       exactWithDefault.Add(result.Exact[i]);
     result.Exact = exactWithDefault;
     #endregion    
   }
   return result;
 }