GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/preprocessing/passes/sep_skolem_emp.cpp Lines: 49 55 89.1 %
Date: 2021-11-07 Branches: 98 198 49.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Yoni Zohar, Andrew Reynolds, Gereon Kremer
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
 * The sep-pre-skolem-emp preprocessing pass.
14
 */
15
16
#include "preprocessing/passes/sep_skolem_emp.h"
17
18
#include <string>
19
#include <unordered_map>
20
#include <vector>
21
22
#include "expr/node.h"
23
#include "expr/skolem_manager.h"
24
#include "preprocessing/assertion_pipeline.h"
25
#include "preprocessing/preprocessing_pass_context.h"
26
#include "theory/quantifiers/quant_util.h"
27
#include "theory/rewriter.h"
28
#include "theory/theory.h"
29
#include "theory/theory_engine.h"
30
31
namespace cvc5 {
32
namespace preprocessing {
33
namespace passes {
34
35
using namespace std;
36
using namespace cvc5::theory;
37
38
namespace {
39
40
3
Node preSkolemEmp(TypeNode locType,
41
                  TypeNode dataType,
42
                  Node n,
43
                  bool pol,
44
                  std::map<bool, std::map<Node, Node>>& visited)
45
{
46
3
  std::map<Node, Node>::iterator it = visited[pol].find(n);
47
3
  if (it == visited[pol].end())
48
  {
49
3
    NodeManager* nm = NodeManager::currentNM();
50
3
    SkolemManager* sm = nm->getSkolemManager();
51
6
    Trace("sep-preprocess") << "Pre-skolem emp " << n << " with pol " << pol
52
3
                            << std::endl;
53
6
    Node ret = n;
54
3
    if (n.getKind() == kind::SEP_EMP)
55
    {
56
1
      if (!pol)
57
      {
58
        Node x =
59
2
            sm->mkDummySkolem("ex", locType, "skolem location for negated emp");
60
        Node y =
61
2
            sm->mkDummySkolem("ey", dataType, "skolem data for negated emp");
62
        return nm
63
4
            ->mkNode(kind::SEP_STAR,
64
2
                     nm->mkNode(kind::SEP_PTO, x, y),
65
2
                     nm->mkConst(true))
66
1
            .negate();
67
      }
68
    }
69
2
    else if (n.getKind() != kind::FORALL && n.getNumChildren() > 0)
70
    {
71
1
      std::vector<Node> children;
72
1
      bool childChanged = false;
73
1
      if (n.getMetaKind() == kind::metakind::PARAMETERIZED)
74
      {
75
        children.push_back(n.getOperator());
76
      }
77
2
      for (unsigned i = 0; i < n.getNumChildren(); i++)
78
      {
79
        bool newPol, newHasPol;
80
1
        QuantPhaseReq::getPolarity(n, i, true, pol, newHasPol, newPol);
81
2
        Node nc = n[i];
82
1
        if (newHasPol)
83
        {
84
1
          nc = preSkolemEmp(locType, dataType, n[i], newPol, visited);
85
1
          childChanged = childChanged || nc != n[i];
86
        }
87
1
        children.push_back(nc);
88
      }
89
1
      if (childChanged)
90
      {
91
1
        return nm->mkNode(n.getKind(), children);
92
      }
93
    }
94
1
    visited[pol][n] = ret;
95
1
    return n;
96
  }
97
  else
98
  {
99
    return it->second;
100
  }
101
}
102
103
}  // namespace
104
105
15340
SepSkolemEmp::SepSkolemEmp(PreprocessingPassContext* preprocContext)
106
15340
    : PreprocessingPass(preprocContext, "sep-skolem-emp"){};
107
108
1
PreprocessingPassResult SepSkolemEmp::applyInternal(
109
    AssertionPipeline* assertionsToPreprocess)
110
{
111
2
  TypeNode locType, dataType;
112
1
  if (!d_preprocContext->getTheoryEngine()->getSepHeapTypes(locType, dataType))
113
  {
114
    warning() << "SepSkolemEmp::applyInternal: failed to get separation logic "
115
                 "heap types during preprocessing"
116
              << std::endl;
117
    return PreprocessingPassResult::NO_CONFLICT;
118
  }
119
2
  std::map<bool, std::map<Node, Node>> visited;
120
3
  for (unsigned i = 0; i < assertionsToPreprocess->size(); ++i)
121
  {
122
4
    Node prev = (*assertionsToPreprocess)[i];
123
2
    bool pol = true;
124
4
    Node next = preSkolemEmp(locType, dataType, prev, pol, visited);
125
2
    if (next != prev)
126
    {
127
1
      assertionsToPreprocess->replace(i, rewrite(next));
128
1
      Trace("sep-preprocess") << "*** Preprocess sep " << prev << endl;
129
2
      Trace("sep-preprocess") << "   ...got " << (*assertionsToPreprocess)[i]
130
1
                              << endl;
131
    }
132
2
    visited.clear();
133
  }
134
1
  return PreprocessingPassResult::NO_CONFLICT;
135
}
136
137
138
}  // namespace passes
139
}  // namespace preprocessing
140
31137
}  // namespace cvc5