GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/uf/theory_uf_type_rules.cpp Lines: 51 75 68.0 %
Date: 2021-08-17 Branches: 88 318 27.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Tim King, Morgan Deters
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
 * Typing and cardinality rules for the theory of UF.
14
 */
15
16
#include "theory/uf/theory_uf_type_rules.h"
17
18
#include <climits>
19
#include <sstream>
20
21
#include "util/rational.h"
22
23
namespace cvc5 {
24
namespace theory {
25
namespace uf {
26
27
457386
TypeNode UfTypeRule::computeType(NodeManager* nodeManager, TNode n, bool check)
28
{
29
914772
  TNode f = n.getOperator();
30
914772
  TypeNode fType = f.getType(check);
31
457386
  if (!fType.isFunction())
32
  {
33
    throw TypeCheckingExceptionPrivate(n,
34
                                       "operator does not have function type");
35
  }
36
457386
  if (check)
37
  {
38
457386
    if (n.getNumChildren() != fType.getNumChildren() - 1)
39
    {
40
      throw TypeCheckingExceptionPrivate(
41
          n, "number of arguments does not match the function type");
42
    }
43
457386
    TNode::iterator argument_it = n.begin();
44
457386
    TNode::iterator argument_it_end = n.end();
45
457386
    TypeNode::iterator argument_type_it = fType.begin();
46
14349166
    for (; argument_it != argument_it_end; ++argument_it, ++argument_type_it)
47
    {
48
13891780
      TypeNode currentArgument = (*argument_it).getType();
49
13891780
      TypeNode currentArgumentType = *argument_type_it;
50
6945890
      if (!currentArgument.isSubtypeOf(currentArgumentType))
51
      {
52
        std::stringstream ss;
53
        ss << "argument type is not a subtype of the function's argument "
54
           << "type:\n"
55
           << "argument:  " << *argument_it << "\n"
56
           << "has type:  " << (*argument_it).getType() << "\n"
57
           << "not subtype: " << *argument_type_it << "\n"
58
           << "in term : " << n;
59
        throw TypeCheckingExceptionPrivate(n, ss.str());
60
      }
61
    }
62
  }
63
914772
  return fType.getRangeType();
64
}
65
66
1099
TypeNode CardinalityConstraintTypeRule::computeType(NodeManager* nodeManager,
67
                                                    TNode n,
68
                                                    bool check)
69
{
70
1099
  if (check)
71
  {
72
    // don't care what it is, but it should be well-typed
73
1099
    n[0].getType(check);
74
75
2198
    TypeNode valType = n[1].getType(check);
76
1099
    if (valType != nodeManager->integerType())
77
    {
78
      throw TypeCheckingExceptionPrivate(
79
          n, "cardinality constraint must be integer");
80
    }
81
1099
    if (n[1].getKind() != kind::CONST_RATIONAL)
82
    {
83
      throw TypeCheckingExceptionPrivate(
84
          n, "cardinality constraint must be a constant");
85
    }
86
2198
    cvc5::Rational r(INT_MAX);
87
1099
    if (n[1].getConst<Rational>() > r)
88
    {
89
      throw TypeCheckingExceptionPrivate(
90
          n, "Exceeded INT_MAX in cardinality constraint");
91
    }
92
1099
    if (n[1].getConst<Rational>().getNumerator().sgn() != 1)
93
    {
94
      throw TypeCheckingExceptionPrivate(
95
          n, "cardinality constraint must be positive");
96
    }
97
  }
98
1099
  return nodeManager->booleanType();
99
}
100
101
639
TypeNode CombinedCardinalityConstraintTypeRule::computeType(
102
    NodeManager* nodeManager, TNode n, bool check)
103
{
104
639
  if (check)
105
  {
106
1278
    TypeNode valType = n[0].getType(check);
107
639
    if (valType != nodeManager->integerType())
108
    {
109
      throw TypeCheckingExceptionPrivate(
110
          n, "combined cardinality constraint must be integer");
111
    }
112
639
    if (n[0].getKind() != kind::CONST_RATIONAL)
113
    {
114
      throw TypeCheckingExceptionPrivate(
115
          n, "combined cardinality constraint must be a constant");
116
    }
117
1278
    cvc5::Rational r(INT_MAX);
118
639
    if (n[0].getConst<Rational>() > r)
119
    {
120
      throw TypeCheckingExceptionPrivate(
121
          n, "Exceeded INT_MAX in combined cardinality constraint");
122
    }
123
639
    if (n[0].getConst<Rational>().getNumerator().sgn() == -1)
124
    {
125
      throw TypeCheckingExceptionPrivate(
126
          n, "combined cardinality constraint must be non-negative");
127
    }
128
  }
129
639
  return nodeManager->booleanType();
130
}
131
132
TypeNode PartialTypeRule::computeType(NodeManager* nodeManager,
133
                                      TNode n,
134
                                      bool check)
135
{
136
  return n.getOperator().getType().getRangeType();
137
}
138
139
TypeNode CardinalityValueTypeRule::computeType(NodeManager* nodeManager,
140
                                               TNode n,
141
                                               bool check)
142
{
143
  if (check)
144
  {
145
    n[0].getType(check);
146
  }
147
  return nodeManager->integerType();
148
}
149
150
13789
TypeNode HoApplyTypeRule::computeType(NodeManager* nodeManager,
151
                                      TNode n,
152
                                      bool check)
153
{
154
13789
  Assert(n.getKind() == kind::HO_APPLY);
155
27578
  TypeNode fType = n[0].getType(check);
156
13789
  if (!fType.isFunction())
157
  {
158
    throw TypeCheckingExceptionPrivate(
159
        n, "first argument does not have function type");
160
  }
161
13789
  Assert(fType.getNumChildren() >= 2);
162
13789
  if (check)
163
  {
164
27578
    TypeNode aType = n[1].getType(check);
165
13789
    if (!aType.isSubtypeOf(fType[0]))
166
    {
167
      throw TypeCheckingExceptionPrivate(
168
          n, "argument does not match function type");
169
    }
170
  }
171
13789
  if (fType.getNumChildren() == 2)
172
  {
173
6769
    return fType.getRangeType();
174
  }
175
  else
176
  {
177
14040
    std::vector<TypeNode> children;
178
7020
    TypeNode::iterator argument_type_it = fType.begin();
179
7020
    TypeNode::iterator argument_type_it_end = fType.end();
180
7020
    ++argument_type_it;
181
38916
    for (; argument_type_it != argument_type_it_end; ++argument_type_it)
182
    {
183
15948
      children.push_back(*argument_type_it);
184
    }
185
7020
    return nodeManager->mkFunctionType(children);
186
  }
187
}
188
189
}  // namespace uf
190
}  // namespace theory
191
29337
}  // namespace cvc5