GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/dtype_cons.cpp Lines: 315 338 93.2 %
Date: 2021-05-22 Branches: 492 1306 37.7 %

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