GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/builtin/theory_builtin_type_rules.h Lines: 64 87 73.6 %
Date: 2021-09-15 Branches: 152 406 37.4 %

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
5713871
  inline static TypeNode computeType(NodeManager* nodeManager,
34
                                     TNode n,
35
                                     bool check)
36
  {
37
5713871
    TypeNode booleanType = nodeManager->booleanType();
38
39
5713871
    if (check)
40
    {
41
11427742
      TypeNode lhsType = n[0].getType(check);
42
11427742
      TypeNode rhsType = n[1].getType(check);
43
44
5713871
      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
5713793
    return booleanType;
57
  }
58
};/* class EqualityTypeRule */
59
60
61
class DistinctTypeRule {
62
 public:
63
10417
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
64
10417
    if( check ) {
65
10417
      TNode::iterator child_it = n.begin();
66
10417
      TNode::iterator child_it_end = n.end();
67
20834
      TypeNode joinType = (*child_it).getType(check);
68
22716
      for (++child_it; child_it != child_it_end; ++child_it) {
69
24598
        TypeNode currentType = (*child_it).getType();
70
12299
        joinType = TypeNode::leastCommonTypeNode(joinType, currentType);
71
12299
        if (joinType.isNull()) {
72
          throw TypeCheckingExceptionPrivate(n, "Not all arguments are of the same type");
73
        }
74
      }
75
    }
76
10417
    return nodeManager->booleanType();
77
  }
78
};/* class DistinctTypeRule */
79
80
class SExprTypeRule {
81
 public:
82
893316
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
83
893316
    if (check)
84
    {
85
3461354
      for (TNode c : n)
86
      {
87
2568038
        c.getType(check);
88
      }
89
    }
90
893316
    return nodeManager->sExprType();
91
  }
92
};/* class SExprTypeRule */
93
94
class UninterpretedConstantTypeRule {
95
 public:
96
  static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check);
97
};/* class UninterpretedConstantTypeRule */
98
99
class AbstractValueTypeRule {
100
 public:
101
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
102
    // An UnknownTypeException means that this node has no type.  For now,
103
    // only abstract values are like this---and then, only if they are created
104
    // by the user and don't actually correspond to one that the SmtEngine gave
105
    // them previously.
106
    throw UnknownTypeException(n);
107
  }
108
};/* class AbstractValueTypeRule */
109
110
class LambdaTypeRule {
111
 public:
112
19646
  inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
113
19646
    if( n[0].getType(check) != nodeManager->boundVarListType() ) {
114
      std::stringstream ss;
115
      ss << "expected a bound var list for LAMBDA expression, got `"
116
         << n[0].getType().toString() << "'";
117
      throw TypeCheckingExceptionPrivate(n, ss.str());
118
    }
119
39292
    std::vector<TypeNode> argTypes;
120
83407
    for(TNode::iterator i = n[0].begin(); i != n[0].end(); ++i) {
121
63761
      argTypes.push_back((*i).getType());
122
    }
123
39292
    TypeNode rangeType = n[1].getType(check);
124
39292
    return nodeManager->mkFunctionType(argTypes, rangeType);
125
  }
126
  // computes whether a lambda is a constant value, via conversion to array representation
127
2198
  inline static bool computeIsConst(NodeManager* nodeManager, TNode n)
128
  {
129
2198
    Assert(n.getKind() == kind::LAMBDA);
130
    //get array representation of this function, if possible
131
4396
    Node na = TheoryBuiltinRewriter::getArrayRepresentationForLambda(n);
132
2198
    if( !na.isNull() ){
133
486
      Assert(na.getType().isArray());
134
486
      Trace("lambda-const") << "Array representation for " << n << " is " << na << " " << na.getType() << std::endl;
135
      // must have the standard bound variable list
136
617
      Node bvl = NodeManager::currentNM()->getBoundVarListForFunctionType( n.getType() );
137
486
      if( bvl==n[0] ){
138
        //array must be constant
139
355
        if( na.isConst() ){
140
355
          Trace("lambda-const") << "*** Constant lambda : " << n;
141
355
          Trace("lambda-const") << " since its array representation : " << na << " is constant." << std::endl;
142
355
          return true;
143
        }else{
144
          Trace("lambda-const") << "Non-constant lambda : " << n << " since array is not constant." << std::endl;
145
        }
146
      }else{
147
131
        Trace("lambda-const") << "Non-constant lambda : " << n << " since its varlist is not standard." << std::endl;
148
131
        Trace("lambda-const") << "  standard : " << bvl << std::endl;
149
131
        Trace("lambda-const") << "   current : " << n[0] << std::endl;
150
      }
151
    }else{
152
1712
      Trace("lambda-const") << "Non-constant lambda : " << n << " since it has no array representation." << std::endl;
153
    }
154
1843
    return false;
155
  }
156
};/* class LambdaTypeRule */
157
158
class WitnessTypeRule
159
{
160
 public:
161
3806
  inline static TypeNode computeType(NodeManager* nodeManager,
162
                                     TNode n,
163
                                     bool check)
164
  {
165
3806
    if (n[0].getType(check) != nodeManager->boundVarListType())
166
    {
167
      std::stringstream ss;
168
      ss << "expected a bound var list for WITNESS expression, got `"
169
         << n[0].getType().toString() << "'";
170
      throw TypeCheckingExceptionPrivate(n, ss.str());
171
    }
172
3806
    if (n[0].getNumChildren() != 1)
173
    {
174
      std::stringstream ss;
175
      ss << "expected a bound var list with one argument for WITNESS expression";
176
      throw TypeCheckingExceptionPrivate(n, ss.str());
177
    }
178
3806
    if (check)
179
    {
180
7612
      TypeNode rangeType = n[1].getType(check);
181
3806
      if (!rangeType.isBoolean())
182
      {
183
        std::stringstream ss;
184
        ss << "expected a body of a WITNESS expression to have Boolean type";
185
        throw TypeCheckingExceptionPrivate(n, ss.str());
186
      }
187
    }
188
    // The type of a witness function is the type of its bound variable.
189
3806
    return n[0][0].getType();
190
  }
191
}; /* class WitnessTypeRule */
192
193
class SortProperties {
194
 public:
195
  inline static bool isWellFounded(TypeNode type) {
196
    return true;
197
  }
198
  static Node mkGroundTerm(TypeNode type);
199
};/* class SortProperties */
200
201
class FunctionProperties {
202
 public:
203
  static Cardinality computeCardinality(TypeNode type);
204
205
  /** Function type is well-founded if its component sorts are */
206
  static bool isWellFounded(TypeNode type)
207
  {
208
    for (TypeNode::iterator i = type.begin(), i_end = type.end(); i != i_end;
209
         ++i)
210
    {
211
      if (!(*i).isWellFounded())
212
      {
213
        return false;
214
      }
215
    }
216
    return true;
217
  }
218
  /**
219
   * Ground term for function sorts is (lambda x. t) where x is the
220
   * canonical variable list for its type and t is the canonical ground term of
221
   * its range.
222
   */
223
1
  static Node mkGroundTerm(TypeNode type)
224
  {
225
1
    NodeManager* nm = NodeManager::currentNM();
226
2
    Node bvl = nm->getBoundVarListForFunctionType(type);
227
2
    Node ret = type.getRangeType().mkGroundTerm();
228
2
    return nm->mkNode(kind::LAMBDA, bvl, ret);
229
  }
230
};/* class FuctionProperties */
231
232
}  // namespace builtin
233
}  // namespace theory
234
}  // namespace cvc5
235
236
#endif /* CVC5__THEORY__BUILTIN__THEORY_BUILTIN_TYPE_RULES_H */