GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/dtype_cons.cpp Lines: 319 338 94.4 %
Date: 2021-09-17 Branches: 506 1300 38.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Tim King
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
 * A class representing a datatype definition.
14
 */
15
#include "expr/dtype_cons.h"
16
17
#include "expr/ascription_type.h"
18
#include "expr/dtype.h"
19
#include "expr/node_manager.h"
20
#include "expr/skolem_manager.h"
21
#include "expr/type_matcher.h"
22
#include "options/datatypes_options.h"
23
24
using namespace cvc5::kind;
25
using namespace cvc5::theory;
26
27
namespace cvc5 {
28
29
16574
DTypeConstructor::DTypeConstructor(std::string name,
30
16574
                                   unsigned weight)
31
    :  // We don't want to introduce a new data member, because eventually
32
       // we're going to be a constant stuffed inside a node.  So we stow
33
       // the tester name away inside the constructor name until
34
       // resolution.
35
      d_name(name),
36
      d_tester(),
37
      d_args(),
38
16574
      d_weight(weight)
39
{
40
16574
  Assert(name != "");
41
16574
}
42
43
16683
void DTypeConstructor::addArg(std::string selectorName, TypeNode selectorType)
44
{
45
  // We don't want to introduce a new data member, because eventually
46
  // we're going to be a constant stuffed inside a node.  So we stow
47
  // the selector type away inside a var until resolution (when we can
48
  // create the proper selector type)
49
16683
  Assert(!isResolved());
50
16683
  Assert(!selectorType.isNull());
51
16683
  SkolemManager* sm = NodeManager::currentNM()->getSkolemManager();
52
  Node sel = sm->mkDummySkolem(
53
33366
      "unresolved_" + selectorName,
54
      selectorType,
55
      "is an unresolved selector type placeholder",
56
66732
      NodeManager::SKOLEM_EXACT_NAME | NodeManager::SKOLEM_NO_NOTIFY);
57
  // can use null updater for now
58
33366
  Node nullNode;
59
16683
  Trace("datatypes") << "DTypeConstructor::addArg: " << sel << std::endl;
60
  std::shared_ptr<DTypeSelector> a =
61
33366
      std::make_shared<DTypeSelector>(selectorName, sel, nullNode);
62
16683
  addArg(a);
63
16683
}
64
65
16751
void DTypeConstructor::addArg(std::shared_ptr<DTypeSelector> a)
66
{
67
16751
  d_args.push_back(a);
68
16751
}
69
70
68
void DTypeConstructor::addArgSelf(std::string selectorName)
71
{
72
68
  Trace("datatypes") << "DTypeConstructor::addArgSelf" << std::endl;
73
136
  Node nullNode;
74
  std::shared_ptr<DTypeSelector> a =
75
136
      std::make_shared<DTypeSelector>(selectorName + '\0', nullNode, nullNode);
76
68
  addArg(a);
77
68
}
78
79
36078
const std::string& DTypeConstructor::getName() const { return d_name; }
80
81
525046
Node DTypeConstructor::getConstructor() const
82
{
83
525046
  Assert(isResolved());
84
525046
  return d_constructor;
85
}
86
87
215143
Node DTypeConstructor::getTester() const
88
{
89
215143
  Assert(isResolved());
90
215143
  return d_tester;
91
}
92
93
11360
void DTypeConstructor::setSygus(Node op)
94
{
95
11360
  Assert(!isResolved());
96
11360
  d_sygusOp = op;
97
11360
}
98
99
1423907
Node DTypeConstructor::getSygusOp() const
100
{
101
1423907
  Assert(isResolved());
102
1423907
  return d_sygusOp;
103
}
104
105
686
bool DTypeConstructor::isSygusIdFunc() const
106
{
107
686
  Assert(isResolved());
108
1655
  return (d_sygusOp.getKind() == LAMBDA && d_sygusOp[0].getNumChildren() == 1
109
2158
          && d_sygusOp[0][0] == d_sygusOp[1]);
110
}
111
112
297774
unsigned DTypeConstructor::getWeight() const
113
{
114
297774
  Assert(isResolved());
115
297774
  return d_weight;
116
}
117
118
7631544
size_t DTypeConstructor::getNumArgs() const { return d_args.size(); }
119
120
4824
TypeNode DTypeConstructor::getSpecializedConstructorType(
121
    TypeNode returnType) const
122
{
123
4824
  Assert(isResolved());
124
4824
  Assert(returnType.isDatatype())
125
      << "DTypeConstructor::getSpecializedConstructorType: expected datatype, "
126
         "got "
127
      << returnType;
128
9648
  TypeNode ctn = d_constructor.getType();
129
4824
  const DType& dt = DType::datatypeOf(d_constructor);
130
4824
  if (!dt.isParametric())
131
  {
132
    // if the datatype is not parametric, then no specialization is needed
133
2532
    return ctn;
134
  }
135
4584
  TypeNode dtt = dt.getTypeNode();
136
4584
  TypeMatcher m(dtt);
137
2292
  m.doMatching(dtt, returnType);
138
4584
  std::vector<TypeNode> subst;
139
2292
  m.getMatches(subst);
140
4584
  std::vector<TypeNode> params = dt.getParameters();
141
  return ctn.substitute(
142
2292
      params.begin(), params.end(), subst.begin(), subst.end());
143
}
144
145
2138
const std::vector<std::shared_ptr<DTypeSelector> >& DTypeConstructor::getArgs()
146
    const
147
{
148
2138
  return d_args;
149
}
150
151
Cardinality DTypeConstructor::getCardinality(TypeNode t) const
152
{
153
  Assert(isResolved());
154
155
  Cardinality c = 1;
156
157
  for (size_t i = 0, nargs = d_args.size(); i < nargs; i++)
158
  {
159
    c *= getArgType(i).getCardinality();
160
  }
161
162
  return c;
163
}
164
165
103837
CardinalityClass DTypeConstructor::getCardinalityClass(TypeNode t) const
166
{
167
103837
  std::pair<CardinalityClass, bool> cinfo = computeCardinalityInfo(t);
168
103837
  return cinfo.first;
169
}
170
171
118190
bool DTypeConstructor::hasFiniteExternalArgType(TypeNode t) const
172
{
173
118190
  std::pair<CardinalityClass, bool> cinfo = computeCardinalityInfo(t);
174
118190
  return cinfo.second;
175
}
176
177
222027
std::pair<CardinalityClass, bool> DTypeConstructor::computeCardinalityInfo(
178
    TypeNode t) const
179
{
180
  std::map<TypeNode, std::pair<CardinalityClass, bool> >::iterator it =
181
222027
      d_cardInfo.find(t);
182
222027
  if (it != d_cardInfo.end())
183
  {
184
213460
    return it->second;
185
  }
186
8567
  std::pair<CardinalityClass, bool> ret(CardinalityClass::ONE, false);
187
17134
  std::vector<TypeNode> instTypes;
188
17134
  std::vector<TypeNode> paramTypes;
189
8567
  bool isParam = t.isParametricDatatype();
190
8567
  if (isParam)
191
  {
192
87
    paramTypes = t.getDType().getParameters();
193
87
    instTypes = t.getParamTypes();
194
  }
195
18553
  for (unsigned i = 0, nargs = getNumArgs(); i < nargs; i++)
196
  {
197
19972
    TypeNode tc = getArgType(i);
198
9986
    if (isParam)
199
    {
200
105
      tc = tc.substitute(paramTypes.begin(),
201
                         paramTypes.end(),
202
                         instTypes.begin(),
203
                         instTypes.end());
204
    }
205
    // get the current cardinality class
206
9986
    CardinalityClass cctc = tc.getCardinalityClass();
207
    // update ret.first to the max cardinality class
208
9986
    ret.first = maxCardinalityClass(ret.first, cctc);
209
9986
    if (cctc != CardinalityClass::INFINITE)
210
    {
211
      // if the argument is (interpreted) finite and external, set the flag
212
      // for indicating it has a finite external argument
213
1362
      ret.second = ret.second || !tc.isDatatype();
214
    }
215
  }
216
8567
  d_cardInfo[t] = ret;
217
8567
  return ret;
218
}
219
220
3251089
bool DTypeConstructor::isResolved() const { return !d_tester.isNull(); }
221
222
1646062
const DTypeSelector& DTypeConstructor::operator[](size_t index) const
223
{
224
1646062
  Assert(index < getNumArgs());
225
1646062
  return *d_args[index];
226
}
227
228
614297
TypeNode DTypeConstructor::getArgType(size_t index) const
229
{
230
614297
  Assert(index < getNumArgs());
231
614297
  return (*this)[index].getType().getSelectorRangeType();
232
}
233
234
365497
Node DTypeConstructor::getSelectorInternal(TypeNode domainType,
235
                                           size_t index) const
236
{
237
365497
  Assert(isResolved());
238
365497
  Assert(index < getNumArgs());
239
365497
  if (options::dtSharedSelectors())
240
  {
241
235625
    computeSharedSelectors(domainType);
242
235625
    Assert(d_sharedSelectors[domainType].size() == getNumArgs());
243
235625
    return d_sharedSelectors[domainType][index];
244
  }
245
  else
246
  {
247
129872
    return d_args[index]->getSelector();
248
  }
249
}
250
251
317455
int DTypeConstructor::getSelectorIndexInternal(Node sel) const
252
{
253
317455
  Assert(isResolved());
254
317455
  if (options::dtSharedSelectors())
255
  {
256
183346
    Assert(sel.getType().isSelector());
257
281081
    TypeNode domainType = sel.getType().getSelectorDomainType();
258
183346
    computeSharedSelectors(domainType);
259
    std::map<Node, unsigned>::iterator its =
260
183346
        d_sharedSelectorIndex[domainType].find(sel);
261
183346
    if (its != d_sharedSelectorIndex[domainType].end())
262
    {
263
85611
      return (int)its->second;
264
    }
265
  }
266
  else
267
  {
268
134109
    unsigned sindex = DType::indexOf(sel);
269
134109
    if (getNumArgs() > sindex && d_args[sindex]->getSelector() == sel)
270
    {
271
61304
      return static_cast<int>(sindex);
272
    }
273
  }
274
170540
  return -1;
275
}
276
277
14
int DTypeConstructor::getSelectorIndexForName(const std::string& name) const
278
{
279
18
  for (size_t i = 0, nargs = getNumArgs(); i < nargs; i++)
280
  {
281
14
    if (d_args[i]->getName() == name)
282
    {
283
10
      return i;
284
    }
285
  }
286
4
  return -1;
287
}
288
289
16572
bool DTypeConstructor::involvesExternalType() const
290
{
291
30512
  for (size_t i = 0, nargs = getNumArgs(); i < nargs; i++)
292
  {
293
15495
    if (!getArgType(i).isDatatype())
294
    {
295
1555
      return true;
296
    }
297
  }
298
15017
  return false;
299
}
300
301
16572
bool DTypeConstructor::involvesUninterpretedType() const
302
{
303
17141
  for (size_t i = 0, nargs = getNumArgs(); i < nargs; i++)
304
  {
305
8974
    if (!getArgType(i).isSort())
306
    {
307
8405
      return true;
308
    }
309
  }
310
8167
  return false;
311
}
312
313
14051
Cardinality DTypeConstructor::computeCardinality(
314
    TypeNode t, std::vector<TypeNode>& processing) const
315
{
316
14051
  Cardinality c = 1;
317
28102
  std::vector<TypeNode> instTypes;
318
28102
  std::vector<TypeNode> paramTypes;
319
14051
  bool isParam = t.isParametricDatatype();
320
14051
  if (isParam)
321
  {
322
    paramTypes = t.getDType().getParameters();
323
    instTypes = t.getParamTypes();
324
  }
325
19267
  for (size_t i = 0, nargs = d_args.size(); i < nargs; i++)
326
  {
327
10432
    TypeNode tc = getArgType(i);
328
5216
    if (isParam)
329
    {
330
      tc = tc.substitute(paramTypes.begin(),
331
                         paramTypes.end(),
332
                         instTypes.begin(),
333
                         instTypes.end());
334
    }
335
5216
    if (tc.isDatatype())
336
    {
337
4493
      const DType& dt = tc.getDType();
338
4493
      c *= dt.computeCardinality(t, processing);
339
    }
340
    else
341
    {
342
723
      c *= tc.getCardinality();
343
    }
344
  }
345
28102
  return c;
346
}
347
348
6412
bool DTypeConstructor::computeWellFounded(
349
    std::vector<TypeNode>& processing) const
350
{
351
11932
  for (size_t i = 0, nargs = getNumArgs(); i < nargs; i++)
352
  {
353
12140
    TypeNode t = getArgType(i);
354
6620
    if (t.isDatatype())
355
    {
356
3125
      const DType& dt = t.getDType();
357
3125
      if (!dt.computeWellFounded(processing))
358
      {
359
1100
        return false;
360
      }
361
    }
362
  }
363
5312
  return true;
364
}
365
366
1906
Node DTypeConstructor::computeGroundTerm(TypeNode t,
367
                                         std::vector<TypeNode>& processing,
368
                                         std::map<TypeNode, Node>& gt,
369
                                         bool isValue) const
370
{
371
1906
  NodeManager* nm = NodeManager::currentNM();
372
3812
  std::vector<Node> groundTerms;
373
1906
  groundTerms.push_back(getConstructor());
374
3812
  Trace("datatypes-init") << "cons " << d_constructor
375
1906
                          << " computeGroundTerm, isValue = " << isValue
376
1906
                          << std::endl;
377
378
  // for each selector, get a ground term
379
3812
  std::vector<TypeNode> instTypes;
380
3812
  std::vector<TypeNode> paramTypes;
381
1906
  bool isParam = t.isParametricDatatype();
382
1906
  if (isParam)
383
  {
384
29
    paramTypes = t.getDType().getParameters();
385
29
    instTypes = TypeNode(t).getParamTypes();
386
  }
387
2775
  for (size_t i = 0, nargs = getNumArgs(); i < nargs; i++)
388
  {
389
1830
    TypeNode selType = getArgType(i);
390
961
    if (isParam)
391
    {
392
20
      selType = selType.substitute(paramTypes.begin(),
393
                                   paramTypes.end(),
394
                                   instTypes.begin(),
395
                                   instTypes.end());
396
    }
397
1830
    Node arg;
398
961
    if (selType.isDatatype())
399
    {
400
600
      std::map<TypeNode, Node>::iterator itgt = gt.find(selType);
401
600
      if (itgt != gt.end())
402
      {
403
1
        arg = itgt->second;
404
      }
405
      else
406
      {
407
599
        const DType& dt = selType.getDType();
408
599
        arg = dt.computeGroundTerm(selType, processing, isValue);
409
      }
410
    }
411
    else
412
    {
413
      // call mkGroundValue or mkGroundTerm based on isValue
414
361
      arg = isValue ? selType.mkGroundValue() : selType.mkGroundTerm();
415
    }
416
961
    if (arg.isNull())
417
    {
418
184
      Trace("datatypes-init") << "...unable to construct arg of "
419
92
                              << d_args[i]->getName() << std::endl;
420
92
      return Node();
421
    }
422
    else
423
    {
424
1738
      Trace("datatypes-init")
425
1738
          << "...constructed arg " << arg << " of type " << arg.getType()
426
869
          << ", isConst = " << arg.isConst() << std::endl;
427
1738
      Assert(!isValue || arg.isConst())
428
869
          << "Expected non-constant constructor argument : " << arg
429
869
          << " of type " << arg.getType();
430
869
      groundTerms.push_back(arg);
431
    }
432
  }
433
434
3628
  Node groundTerm = nm->mkNode(APPLY_CONSTRUCTOR, groundTerms);
435
1814
  if (isParam)
436
  {
437
28
    Assert(DType::datatypeOf(d_constructor).isParametric());
438
    // type is parametric, must apply type ascription
439
56
    Trace("datatypes-init") << "ambiguous type for " << groundTerm
440
28
                            << ", ascribe to " << t << std::endl;
441
84
    groundTerms[0] = nm->mkNode(
442
        APPLY_TYPE_ASCRIPTION,
443
56
        nm->mkConst(AscriptionType(getSpecializedConstructorType(t))),
444
28
        groundTerms[0]);
445
28
    groundTerm = nm->mkNode(APPLY_CONSTRUCTOR, groundTerms);
446
  }
447
1814
  Trace("datatypes-init") << "...return " << groundTerm << std::endl;
448
1814
  Assert(!isValue || groundTerm.isConst()) << "Non-constant term " << groundTerm
449
                                           << " returned for computeGroundTerm";
450
1814
  return groundTerm;
451
}
452
453
418971
void DTypeConstructor::computeSharedSelectors(TypeNode domainType) const
454
{
455
418971
  if (d_sharedSelectors[domainType].size() < getNumArgs())
456
  {
457
1426
    TypeNode ctype;
458
713
    if (domainType.isParametricDatatype())
459
    {
460
2
      ctype = getSpecializedConstructorType(domainType);
461
    }
462
    else
463
    {
464
711
      ctype = d_constructor.getType();
465
    }
466
713
    Assert(ctype.isConstructor());
467
713
    Assert(ctype.getNumChildren() - 1 == getNumArgs());
468
    // compute the shared selectors
469
713
    const DType& dt = DType::datatypeOf(d_constructor);
470
1426
    std::map<TypeNode, unsigned> counter;
471
2088
    for (size_t j = 0, jend = ctype.getNumChildren() - 1; j < jend; j++)
472
    {
473
2750
      TypeNode t = ctype[j];
474
2750
      Node ss = dt.getSharedSelector(domainType, t, counter[t]);
475
1375
      d_sharedSelectors[domainType].push_back(ss);
476
1375
      Assert(d_sharedSelectorIndex[domainType].find(ss)
477
             == d_sharedSelectorIndex[domainType].end());
478
1375
      d_sharedSelectorIndex[domainType][ss] = j;
479
1375
      counter[t]++;
480
    }
481
  }
482
418971
}
483
484
16572
bool DTypeConstructor::resolve(
485
    TypeNode self,
486
    const std::map<std::string, TypeNode>& resolutions,
487
    const std::vector<TypeNode>& placeholders,
488
    const std::vector<TypeNode>& replacements,
489
    const std::vector<TypeNode>& paramTypes,
490
    const std::vector<TypeNode>& paramReplacements,
491
    size_t cindex)
492
{
493
16572
  if (isResolved())
494
  {
495
    // already resolved, fail
496
    return false;
497
  }
498
33144
  Trace("datatypes") << "DTypeConstructor::resolve, self type is " << self
499
16572
                     << std::endl;
500
501
16572
  NodeManager* nm = NodeManager::currentNM();
502
16572
  SkolemManager* sm = nm->getSkolemManager();
503
16572
  size_t index = 0;
504
33144
  std::vector<TypeNode> argTypes;
505
16572
  Trace("datatypes-init") << "Initialize constructor " << d_name << std::endl;
506
33323
  for (std::shared_ptr<DTypeSelector> arg : d_args)
507
  {
508
33502
    std::string argName = arg->d_name;
509
33502
    TypeNode range;
510
16751
    if (arg->d_selector.isNull())
511
    {
512
      // the unresolved type wasn't created here; do name resolution
513
136
      std::string typeName = argName.substr(argName.find('\0') + 1);
514
136
      Trace("datatypes-init")
515
68
          << "  - selector, typeName is " << typeName << std::endl;
516
68
      argName.resize(argName.find('\0'));
517
68
      if (typeName == "")
518
      {
519
68
        Trace("datatypes-init") << "  ...self selector" << std::endl;
520
68
        range = self;
521
      }
522
      else
523
      {
524
        std::map<std::string, TypeNode>::const_iterator j =
525
            resolutions.find(typeName);
526
        if (j == resolutions.end())
527
        {
528
          Trace("datatypes-init")
529
              << "  ...failed to resolve selector" << std::endl;
530
          // failed to resolve selector
531
          return false;
532
        }
533
        else
534
        {
535
          Trace("datatypes-init") << "  ...resolved selector" << std::endl;
536
          range = (*j).second;
537
        }
538
      }
539
    }
540
    else
541
    {
542
      // the type for the selector already exists; may need
543
      // complex-type substitution
544
16683
      range = arg->d_selector.getType();
545
33366
      Trace("datatypes-init")
546
16683
          << "  - null selector, range = " << range << std::endl;
547
16683
      if (!placeholders.empty())
548
      {
549
15310
        range = range.substitute(placeholders.begin(),
550
                                 placeholders.end(),
551
                                 replacements.begin(),
552
                                 replacements.end());
553
      }
554
33366
      Trace("datatypes-init")
555
16683
          << "  ...range after placeholder replacement " << range << std::endl;
556
16683
      if (!paramTypes.empty())
557
      {
558
108
        range = doParametricSubstitution(range, paramTypes, paramReplacements);
559
      }
560
33366
      Trace("datatypes-init")
561
16683
          << "  ...range after parametric substitution " << range << std::endl;
562
    }
563
    // Internally, selectors (and updaters) are fresh internal skolems which
564
    // we constructor via mkDummySkolem.
565
67004
    arg->d_selector = sm->mkDummySkolem(
566
        argName,
567
33502
        nm->mkSelectorType(self, range),
568
        "is a selector",
569
16751
        NodeManager::SKOLEM_EXACT_NAME | NodeManager::SKOLEM_NO_NOTIFY);
570
33502
    std::string updateName("update_" + argName);
571
67004
    arg->d_updater = sm->mkDummySkolem(
572
        updateName,
573
33502
        nm->mkDatatypeUpdateType(self, range),
574
        "is a selector",
575
16751
        NodeManager::SKOLEM_EXACT_NAME | NodeManager::SKOLEM_NO_NOTIFY);
576
    // must set indices to ensure datatypes::utils::indexOf works
577
16751
    arg->d_selector.setAttribute(DTypeConsIndexAttr(), cindex);
578
16751
    arg->d_selector.setAttribute(DTypeIndexAttr(), index);
579
16751
    arg->d_updater.setAttribute(DTypeConsIndexAttr(), cindex);
580
16751
    arg->d_updater.setAttribute(DTypeIndexAttr(), index);
581
16751
    index = index + 1;
582
16751
    arg->d_resolved = true;
583
16751
    argTypes.push_back(range);
584
    // We use \0 as a distinguished marker for unresolved selectors for doing
585
    // name resolutions. We now can remove \0 from name if necessary.
586
16751
    const size_t nul = arg->d_name.find('\0');
587
16751
    if (nul != std::string::npos)
588
    {
589
68
      arg->d_name.resize(nul);
590
    }
591
  }
592
593
16572
  Assert(index == getNumArgs());
594
595
  // Set constructor/tester last, since DTypeConstructor::isResolved()
596
  // returns true when d_tester is not the null Node.  If something
597
  // fails above, we want Constuctor::isResolved() to remain "false".
598
  // Further, mkConstructorType() iterates over the selectors, so
599
  // should get the results of any resolutions we did above.
600
  // The name of the tester variable does not matter, it is only used
601
  // internally.
602
33144
  std::string testerName("is_" + d_name);
603
66288
  d_tester = sm->mkDummySkolem(
604
      testerName,
605
33144
      nm->mkTesterType(self),
606
      "is a tester",
607
16572
      NodeManager::SKOLEM_EXACT_NAME | NodeManager::SKOLEM_NO_NOTIFY);
608
66288
  d_constructor = sm->mkDummySkolem(
609
      getName(),
610
33144
      nm->mkConstructorType(argTypes, self),
611
      "is a constructor",
612
16572
      NodeManager::SKOLEM_EXACT_NAME | NodeManager::SKOLEM_NO_NOTIFY);
613
16572
  Assert(d_constructor.getType().isConstructor());
614
  // associate constructor with all selectors
615
33323
  for (std::shared_ptr<DTypeSelector> sel : d_args)
616
  {
617
16751
    sel->d_constructor = d_constructor;
618
  }
619
16572
  Assert(isResolved());
620
16572
  return true;
621
}
622
623
156
TypeNode DTypeConstructor::doParametricSubstitution(
624
    TypeNode range,
625
    const std::vector<TypeNode>& paramTypes,
626
    const std::vector<TypeNode>& paramReplacements)
627
{
628
156
  if (range.getNumChildren() == 0)
629
  {
630
112
    return range;
631
  }
632
88
  std::vector<TypeNode> origChildren;
633
88
  std::vector<TypeNode> children;
634
92
  for (TypeNode::const_iterator i = range.begin(), iend = range.end();
635
92
       i != iend;
636
       ++i)
637
  {
638
48
    origChildren.push_back((*i));
639
48
    children.push_back(
640
96
        doParametricSubstitution((*i), paramTypes, paramReplacements));
641
  }
642
54
  for (size_t i = 0, psize = paramTypes.size(); i < psize; ++i)
643
  {
644
52
    if (paramTypes[i].getSortConstructorArity() == origChildren.size())
645
    {
646
58
      TypeNode tn = paramTypes[i].instantiateSortConstructor(origChildren);
647
50
      if (range == tn)
648
      {
649
        TypeNode tret =
650
84
            paramReplacements[i].instantiateParametricDatatype(children);
651
42
        return tret;
652
      }
653
    }
654
  }
655
4
  NodeBuilder nb(range.getKind());
656
6
  for (size_t i = 0, csize = children.size(); i < csize; ++i)
657
  {
658
4
    nb << children[i];
659
  }
660
4
  TypeNode tn = nb.constructTypeNode();
661
2
  return tn;
662
}
663
664
38
void DTypeConstructor::toStream(std::ostream& out) const
665
{
666
38
  out << getName();
667
668
38
  unsigned nargs = getNumArgs();
669
38
  if (nargs == 0)
670
  {
671
18
    return;
672
  }
673
20
  out << "(";
674
54
  for (unsigned i = 0; i < nargs; i++)
675
  {
676
34
    out << *d_args[i];
677
34
    if (i + 1 < nargs)
678
    {
679
14
      out << ", ";
680
    }
681
  }
682
20
  out << ")";
683
}
684
685
38
std::ostream& operator<<(std::ostream& os, const DTypeConstructor& ctor)
686
{
687
  // can only output datatypes in the cvc5 native language
688
76
  language::SetLanguage::Scope ls(os, Language::LANG_CVC);
689
38
  ctor.toStream(os);
690
76
  return os;
691
}
692
693
29577
}  // namespace cvc5