GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/builtin/theory_builtin_type_rules.h Lines: 72 95 75.8 %
Date: 2021-05-22 Branches: 163 426 38.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Dejan Jovanovic
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Type rules for the builtin theory.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__BUILTIN__THEORY_BUILTIN_TYPE_RULES_H
19
#define CVC5__THEORY__BUILTIN__THEORY_BUILTIN_TYPE_RULES_H
20
21
#include "expr/node.h"
22
#include "expr/type_node.h"
23
#include "theory/builtin/theory_builtin_rewriter.h" // for array and lambda representation
24
25
#include <sstream>
26
27
namespace cvc5 {
28
namespace theory {
29
namespace builtin {
30
31
class EqualityTypeRule {
32
 public:
33
5065195
  inline static TypeNode computeType(NodeManager* nodeManager,
34
                                     TNode n,
35
                                     bool check)
36
  {
37
5065195
    TypeNode booleanType = nodeManager->booleanType();
38
39
5065195
    if (check)
40
    {
41
10130390
      TypeNode lhsType = n[0].getType(check);
42
10130390
      TypeNode rhsType = n[1].getType(check);
43
44
5065195
      if (TypeNode::leastCommonTypeNode(lhsType, rhsType).isNull())
45
      {
46
156
        std::stringstream ss;
47
78
        ss << "Subexpressions must have a common base type:" << std::endl;
48
92
        ss << "Equation: " << n << std::endl;
49
64
        ss << "Type 1: " << lhsType << std::endl;
50
64
        ss << "Type 2: " << rhsType << std::endl;
51
52
64
        throw TypeCheckingExceptionPrivate(n, ss.str());
53
      }
54
      // TODO : check isFirstClass for these types? (github issue #1202)
55
    }
56
5065117
    return booleanType;
57
  }
58
};/* class EqualityTypeRule */
59
60
61
class DistinctTypeRule {
62
 public:
63
10621
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
64
10621
    if( check ) {
65
10621
      TNode::iterator child_it = n.begin();
66
10621
      TNode::iterator child_it_end = n.end();
67
21242
      TypeNode joinType = (*child_it).getType(check);
68
23038
      for (++child_it; child_it != child_it_end; ++child_it) {
69
24834
        TypeNode currentType = (*child_it).getType();
70
12417
        joinType = TypeNode::leastCommonTypeNode(joinType, currentType);
71
12417
        if (joinType.isNull()) {
72
          throw TypeCheckingExceptionPrivate(n, "Not all arguments are of the same type");
73
        }
74
      }
75
    }
76
10621
    return nodeManager->booleanType();
77
  }
78
};/* class DistinctTypeRule */
79
80
class SExprTypeRule {
81
 public:
82
731606
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
83
731606
    if (check)
84
    {
85
2803159
      for (TNode c : n)
86
      {
87
2071553
        c.getType(check);
88
      }
89
    }
90
731606
    return nodeManager->sExprType();
91
  }
92
};/* class SExprTypeRule */
93
94
class UninterpretedConstantTypeRule {
95
 public:
96
2701
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
97
2701
    return n.getConst<UninterpretedConstant>().getType();
98
  }
99
};/* class UninterpretedConstantTypeRule */
100
101
class AbstractValueTypeRule {
102
 public:
103
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
104
    // An UnknownTypeException means that this node has no type.  For now,
105
    // only abstract values are like this---and then, only if they are created
106
    // by the user and don't actually correspond to one that the SmtEngine gave
107
    // them previously.
108
    throw UnknownTypeException(n);
109
  }
110
};/* class AbstractValueTypeRule */
111
112
class LambdaTypeRule {
113
 public:
114
21340
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
115
21340
    if( n[0].getType(check) != nodeManager->boundVarListType() ) {
116
      std::stringstream ss;
117
      ss << "expected a bound var list for LAMBDA expression, got `"
118
         << n[0].getType().toString() << "'";
119
      throw TypeCheckingExceptionPrivate(n, ss.str());
120
    }
121
42680
    std::vector<TypeNode> argTypes;
122
86335
    for(TNode::iterator i = n[0].begin(); i != n[0].end(); ++i) {
123
64995
      argTypes.push_back((*i).getType());
124
    }
125
42680
    TypeNode rangeType = n[1].getType(check);
126
42680
    return nodeManager->mkFunctionType(argTypes, rangeType);
127
  }
128
  // computes whether a lambda is a constant value, via conversion to array representation
129
1729
  inline static bool computeIsConst(NodeManager* nodeManager, TNode n)
130
  {
131
1729
    Assert(n.getKind() == kind::LAMBDA);
132
    //get array representation of this function, if possible
133
3458
    Node na = TheoryBuiltinRewriter::getArrayRepresentationForLambda(n);
134
1729
    if( !na.isNull() ){
135
500
      Assert(na.getType().isArray());
136
500
      Trace("lambda-const") << "Array representation for " << n << " is " << na << " " << na.getType() << std::endl;
137
      // must have the standard bound variable list
138
619
      Node bvl = NodeManager::currentNM()->getBoundVarListForFunctionType( n.getType() );
139
500
      if( bvl==n[0] ){
140
        //array must be constant
141
381
        if( na.isConst() ){
142
381
          Trace("lambda-const") << "*** Constant lambda : " << n;
143
381
          Trace("lambda-const") << " since its array representation : " << na << " is constant." << std::endl;
144
381
          return true;
145
        }else{
146
          Trace("lambda-const") << "Non-constant lambda : " << n << " since array is not constant." << std::endl;
147
        }
148
      }else{
149
119
        Trace("lambda-const") << "Non-constant lambda : " << n << " since its varlist is not standard." << std::endl;
150
119
        Trace("lambda-const") << "  standard : " << bvl << std::endl;
151
119
        Trace("lambda-const") << "   current : " << n[0] << std::endl;
152
      }
153
    }else{
154
1229
      Trace("lambda-const") << "Non-constant lambda : " << n << " since it has no array representation." << std::endl;
155
    }
156
1348
    return false;
157
  }
158
};/* class LambdaTypeRule */
159
160
class WitnessTypeRule
161
{
162
 public:
163
4729
  inline static TypeNode computeType(NodeManager* nodeManager,
164
                                     TNode n,
165
                                     bool check)
166
  {
167
4729
    if (n[0].getType(check) != nodeManager->boundVarListType())
168
    {
169
      std::stringstream ss;
170
      ss << "expected a bound var list for WITNESS expression, got `"
171
         << n[0].getType().toString() << "'";
172
      throw TypeCheckingExceptionPrivate(n, ss.str());
173
    }
174
4729
    if (n[0].getNumChildren() != 1)
175
    {
176
      std::stringstream ss;
177
      ss << "expected a bound var list with one argument for WITNESS expression";
178
      throw TypeCheckingExceptionPrivate(n, ss.str());
179
    }
180
4729
    if (check)
181
    {
182
9458
      TypeNode rangeType = n[1].getType(check);
183
4729
      if (!rangeType.isBoolean())
184
      {
185
        std::stringstream ss;
186
        ss << "expected a body of a WITNESS expression to have Boolean type";
187
        throw TypeCheckingExceptionPrivate(n, ss.str());
188
      }
189
    }
190
    // The type of a witness function is the type of its bound variable.
191
4729
    return n[0][0].getType();
192
  }
193
}; /* class WitnessTypeRule */
194
195
class SortProperties {
196
 public:
197
  inline static bool isWellFounded(TypeNode type) {
198
    return true;
199
  }
200
  static Node mkGroundTerm(TypeNode type);
201
};/* class SortProperties */
202
203
class FunctionProperties {
204
 public:
205
156
  inline static Cardinality computeCardinality(TypeNode type) {
206
    // Don't assert this; allow other theories to use this cardinality
207
    // computation.
208
    //
209
    // Assert(type.getKind() == kind::FUNCTION_TYPE);
210
211
312
    Cardinality argsCard(1);
212
    // get the largest cardinality of function arguments/return type
213
402
    for(unsigned i = 0, i_end = type.getNumChildren() - 1; i < i_end; ++i) {
214
246
      argsCard *= type[i].getCardinality();
215
    }
216
217
312
    Cardinality valueCard = type[type.getNumChildren() - 1].getCardinality();
218
219
312
    return valueCard ^ argsCard;
220
  }
221
  /** Function type is well-founded if its component sorts are */
222
  static bool isWellFounded(TypeNode type)
223
  {
224
    for (TypeNode::iterator i = type.begin(), i_end = type.end(); i != i_end;
225
         ++i)
226
    {
227
      if (!(*i).isWellFounded())
228
      {
229
        return false;
230
      }
231
    }
232
    return true;
233
  }
234
  /**
235
   * Ground term for function sorts is (lambda x. t) where x is the
236
   * canonical variable list for its type and t is the canonical ground term of
237
   * its range.
238
   */
239
1
  static Node mkGroundTerm(TypeNode type)
240
  {
241
1
    NodeManager* nm = NodeManager::currentNM();
242
2
    Node bvl = nm->getBoundVarListForFunctionType(type);
243
2
    Node ret = type.getRangeType().mkGroundTerm();
244
2
    return nm->mkNode(kind::LAMBDA, bvl, ret);
245
  }
246
};/* class FuctionProperties */
247
248
}  // namespace builtin
249
}  // namespace theory
250
}  // namespace cvc5
251
252
#endif /* CVC5__THEORY__BUILTIN__THEORY_BUILTIN_TYPE_RULES_H */