GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/strings/theory_strings_type_rules.cpp Lines: 97 137 70.8 %
Date: 2021-09-18 Branches: 122 462 26.4 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Aina Niemetz, Yoni Zohar
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 rules for the theory of strings and regexps.
14
 */
15
#include "theory/strings/theory_strings_type_rules.h"
16
17
#include <sstream>
18
19
#include "expr/node_manager.h"
20
#include "expr/sequence.h"
21
#include "options/strings_options.h"
22
#include "util/cardinality.h"
23
24
namespace cvc5 {
25
namespace theory {
26
namespace strings {
27
28
50774
TypeNode StringConcatTypeRule::computeType(NodeManager* nodeManager,
29
                                           TNode n,
30
                                           bool check)
31
{
32
50774
  TypeNode tret;
33
227825
  for (const Node& nc : n)
34
  {
35
354102
    TypeNode t = nc.getType(check);
36
177051
    if (tret.isNull())
37
    {
38
50774
      tret = t;
39
50774
      if (check)
40
      {
41
50774
        if (!t.isStringLike())
42
        {
43
          throw TypeCheckingExceptionPrivate(
44
              n, "expecting string-like terms in concat");
45
        }
46
      }
47
      else
48
      {
49
        break;
50
      }
51
    }
52
126277
    else if (t != tret)
53
    {
54
      throw TypeCheckingExceptionPrivate(
55
          n, "expecting all children to have the same type in concat");
56
    }
57
  }
58
50774
  return tret;
59
}
60
61
46273
TypeNode StringSubstrTypeRule::computeType(NodeManager* nodeManager,
62
                                           TNode n,
63
                                           bool check)
64
{
65
46273
  TypeNode t = n[0].getType(check);
66
46273
  if (check)
67
  {
68
46273
    if (!t.isStringLike())
69
    {
70
      throw TypeCheckingExceptionPrivate(
71
          n, "expecting a string-like term in substr");
72
    }
73
92546
    TypeNode t2 = n[1].getType(check);
74
46273
    if (!t2.isInteger())
75
    {
76
      throw TypeCheckingExceptionPrivate(
77
          n, "expecting an integer start term in substr");
78
    }
79
46273
    t2 = n[2].getType(check);
80
46273
    if (!t2.isInteger())
81
    {
82
      throw TypeCheckingExceptionPrivate(
83
          n, "expecting an integer length term in substr");
84
    }
85
  }
86
46273
  return t;
87
}
88
89
136
TypeNode StringUpdateTypeRule::computeType(NodeManager* nodeManager,
90
                                           TNode n,
91
                                           bool check)
92
{
93
136
  TypeNode t = n[0].getType(check);
94
136
  if (check)
95
  {
96
136
    if (!t.isStringLike())
97
    {
98
      throw TypeCheckingExceptionPrivate(
99
          n, "expecting a string-like term in update");
100
    }
101
272
    TypeNode t2 = n[1].getType(check);
102
136
    if (!t2.isInteger())
103
    {
104
      throw TypeCheckingExceptionPrivate(
105
          n, "expecting an integer start term in update");
106
    }
107
136
    t2 = n[2].getType(check);
108
136
    if (!t2.isStringLike())
109
    {
110
      throw TypeCheckingExceptionPrivate(
111
          n, "expecting an string-like replace term in update");
112
    }
113
  }
114
136
  return t;
115
}
116
117
131
TypeNode StringAtTypeRule::computeType(NodeManager* nodeManager,
118
                                       TNode n,
119
                                       bool check)
120
{
121
131
  TypeNode t = n[0].getType(check);
122
131
  if (check)
123
  {
124
131
    if (!t.isStringLike())
125
    {
126
      throw TypeCheckingExceptionPrivate(
127
          n, "expecting a string-like term in str.at");
128
    }
129
262
    TypeNode t2 = n[1].getType(check);
130
131
    if (!t2.isInteger())
131
    {
132
      throw TypeCheckingExceptionPrivate(
133
          n, "expecting an integer start term in str.at");
134
    }
135
  }
136
131
  return t;
137
}
138
139
3360
TypeNode StringIndexOfTypeRule::computeType(NodeManager* nodeManager,
140
                                            TNode n,
141
                                            bool check)
142
{
143
3360
  if (check)
144
  {
145
6720
    TypeNode t = n[0].getType(check);
146
3360
    if (!t.isStringLike())
147
    {
148
      throw TypeCheckingExceptionPrivate(
149
          n, "expecting a string-like term in indexof");
150
    }
151
6720
    TypeNode t2 = n[1].getType(check);
152
3360
    if (t != t2)
153
    {
154
      throw TypeCheckingExceptionPrivate(
155
          n,
156
          "expecting a term in second argument of indexof that is the same "
157
          "type as the first argument");
158
    }
159
3360
    t = n[2].getType(check);
160
3360
    if (!t.isInteger())
161
    {
162
      throw TypeCheckingExceptionPrivate(
163
          n, "expecting an integer term in third argument of indexof");
164
    }
165
  }
166
3360
  return nodeManager->integerType();
167
}
168
169
3245
TypeNode StringReplaceTypeRule::computeType(NodeManager* nodeManager,
170
                                            TNode n,
171
                                            bool check)
172
{
173
3245
  TypeNode t = n[0].getType(check);
174
3245
  if (check)
175
  {
176
3245
    if (!t.isStringLike())
177
    {
178
      throw TypeCheckingExceptionPrivate(
179
          n, "expecting a string-like term in replace");
180
    }
181
6490
    TypeNode t2 = n[1].getType(check);
182
3245
    if (t != t2)
183
    {
184
      throw TypeCheckingExceptionPrivate(
185
          n,
186
          "expecting a term in second argument of replace that is the same "
187
          "type as the first argument");
188
    }
189
3245
    t2 = n[2].getType(check);
190
3245
    if (t != t2)
191
    {
192
      throw TypeCheckingExceptionPrivate(
193
          n,
194
          "expecting a term in third argument of replace that is the same "
195
          "type as the first argument");
196
    }
197
  }
198
3245
  return t;
199
}
200
201
208
TypeNode StringStrToBoolTypeRule::computeType(NodeManager* nodeManager,
202
                                              TNode n,
203
                                              bool check)
204
{
205
208
  if (check)
206
  {
207
416
    TypeNode t = n[0].getType(check);
208
208
    if (!t.isStringLike())
209
    {
210
      std::stringstream ss;
211
      ss << "expecting a string-like term in argument of " << n.getKind();
212
      throw TypeCheckingExceptionPrivate(n, ss.str());
213
    }
214
  }
215
208
  return nodeManager->booleanType();
216
}
217
218
133710
TypeNode StringStrToIntTypeRule::computeType(NodeManager* nodeManager,
219
                                             TNode n,
220
                                             bool check)
221
{
222
133710
  if (check)
223
  {
224
267420
    TypeNode t = n[0].getType(check);
225
133710
    if (!t.isStringLike())
226
    {
227
      std::stringstream ss;
228
      ss << "expecting a string-like term in argument of " << n.getKind();
229
      throw TypeCheckingExceptionPrivate(n, ss.str());
230
    }
231
  }
232
133710
  return nodeManager->integerType();
233
}
234
235
163
TypeNode StringStrToStrTypeRule::computeType(NodeManager* nodeManager,
236
                                             TNode n,
237
                                             bool check)
238
{
239
163
  TypeNode t = n[0].getType(check);
240
163
  if (check)
241
  {
242
163
    if (!t.isStringLike())
243
    {
244
      std::stringstream ss;
245
      ss << "expecting a string term in argument of " << n.getKind();
246
      throw TypeCheckingExceptionPrivate(n, ss.str());
247
    }
248
  }
249
163
  return t;
250
}
251
252
36794
TypeNode StringRelationTypeRule::computeType(NodeManager* nodeManager,
253
                                             TNode n,
254
                                             bool check)
255
{
256
36794
  if (check)
257
  {
258
73588
    TypeNode t = n[0].getType(check);
259
36794
    if (!t.isStringLike())
260
    {
261
      throw TypeCheckingExceptionPrivate(
262
          n, "expecting a string-like term in relation");
263
    }
264
73588
    TypeNode t2 = n[1].getType(check);
265
36794
    if (t != t2)
266
    {
267
      throw TypeCheckingExceptionPrivate(
268
          n, "expecting two terms of the same string-like type in relation");
269
    }
270
  }
271
36794
  return nodeManager->booleanType();
272
}
273
274
194
TypeNode RegExpRangeTypeRule::computeType(NodeManager* nodeManager,
275
                                          TNode n,
276
                                          bool check)
277
{
278
194
  if (check)
279
  {
280
194
    TNode::iterator it = n.begin();
281
582
    for (int i = 0; i < 2; ++i)
282
    {
283
776
      TypeNode t = (*it).getType(check);
284
388
      if (!t.isString())  // string-only
285
      {
286
        throw TypeCheckingExceptionPrivate(
287
            n, "expecting a string term in regexp range");
288
      }
289
388
      ++it;
290
    }
291
  }
292
194
  return nodeManager->regExpType();
293
}
294
295
429
TypeNode ConstSequenceTypeRule::computeType(NodeManager* nodeManager,
296
                                            TNode n,
297
                                            bool check)
298
{
299
429
  Assert(n.getKind() == kind::CONST_SEQUENCE);
300
429
  return nodeManager->mkSequenceType(n.getConst<Sequence>().getType());
301
}
302
303
272
TypeNode SeqUnitTypeRule::computeType(NodeManager* nodeManager,
304
                                      TNode n,
305
                                      bool check)
306
{
307
272
  return nodeManager->mkSequenceType(n[0].getType(check));
308
}
309
310
226
TypeNode SeqNthTypeRule::computeType(NodeManager* nodeManager,
311
                                     TNode n,
312
                                     bool check)
313
{
314
452
  TypeNode t = n[0].getType(check);
315
226
  TypeNode t1 = t.getSequenceElementType();
316
226
  if (check)
317
  {
318
226
    if (!t.isSequence())
319
    {
320
      throw TypeCheckingExceptionPrivate(n, "expecting a sequence in nth");
321
    }
322
452
    TypeNode t2 = n[1].getType(check);
323
226
    if (!t2.isInteger())
324
    {
325
      throw TypeCheckingExceptionPrivate(
326
          n, "expecting an integer start term in nth");
327
    }
328
  }
329
452
  return t1;
330
}
331
332
Cardinality SequenceProperties::computeCardinality(TypeNode type)
333
{
334
  Assert(type.getKind() == kind::SEQUENCE_TYPE);
335
  return Cardinality::INTEGERS;
336
}
337
/** A sequence is well-founded if its element type is */
338
bool SequenceProperties::isWellFounded(TypeNode type)
339
{
340
  return type[0].isWellFounded();
341
}
342
/** Make ground term for sequence type (return the empty sequence) */
343
Node SequenceProperties::mkGroundTerm(TypeNode type)
344
{
345
  Assert(type.isSequence());
346
  // empty sequence
347
  std::vector<Node> seq;
348
  return NodeManager::currentNM()->mkConst(
349
      Sequence(type.getSequenceElementType(), seq));
350
}
351
}  // namespace strings
352
}  // namespace theory
353
29574
}  // namespace cvc5