1 /*
2
3 This file is part of the Maude 2 interpreter.
4
5 Copyright 1997-2014 SRI International, Menlo Park, CA 94025, USA.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20
21 */
22
23 //
24 // Implementation for class VariableDagNode
25 //
26
27 // utility stuff
28 #include "macros.hh"
29 #include "vector.hh"
30
31 // forward declarations
32 #include "interface.hh"
33 #include "core.hh"
34 #include "variable.hh"
35
36 // interface class definitions
37 #include "symbol.hh"
38 #include "dagNode.hh"
39
40 // core class definitions
41 #include "substitution.hh"
42 #include "narrowingVariableInfo.hh"
43 #include "unificationContext.hh"
44
45 // variable class definitions
46 #include "variableSymbol.hh"
47 #include "variableDagNode.hh"
48
49 RawDagArgumentIterator*
arguments()50 VariableDagNode::arguments()
51 {
52 return 0;
53 }
54
55 size_t
getHashValue()56 VariableDagNode::getHashValue()
57 {
58 return hash(symbol()->getHashValue(), id());
59 }
60
61 int
compareArguments(const DagNode * other) const62 VariableDagNode::compareArguments(const DagNode* other) const
63 {
64 return id() - safeCast(const VariableDagNode*, other)->id();
65 }
66
67 DagNode*
markArguments()68 VariableDagNode::markArguments()
69 {
70 return 0;
71 }
72
73 DagNode*
copyEagerUptoReduced2()74 VariableDagNode::copyEagerUptoReduced2()
75 {
76 return new VariableDagNode(symbol(), id(), index);
77 }
78
79 void
clearCopyPointers2()80 VariableDagNode::clearCopyPointers2()
81 {
82 }
83
84 void
overwriteWithClone(DagNode * old)85 VariableDagNode::overwriteWithClone(DagNode* old)
86 {
87
88 VariableDagNode* d = new(old) VariableDagNode(symbol(), id(), index);
89 d->copySetRewritingFlags(this);
90 d->setSortIndex(getSortIndex());
91 }
92
93 DagNode*
makeClone()94 VariableDagNode::makeClone()
95 {
96 VariableDagNode* d = new VariableDagNode(symbol(), id(), index);
97 d->copySetRewritingFlags(this);
98 d->setSortIndex(getSortIndex());
99 return d;
100 }
101
102 DagNode*
copyWithReplacement(int,DagNode *)103 VariableDagNode::copyWithReplacement(int /* argIndex */, DagNode* /* replacement */)
104 {
105 CantHappen("should never be called");
106 return 0;
107 }
108
109 DagNode*
copyWithReplacement(Vector<RedexPosition> &,int,int)110 VariableDagNode::copyWithReplacement(Vector<RedexPosition>& /* redexStack */,
111 int /* first */,
112 int /* last */)
113 {
114 CantHappen("should never be called");
115 return 0;
116 }
117
118 void
stackArguments(Vector<RedexPosition> &,int,bool)119 VariableDagNode::stackArguments(Vector<RedexPosition>& /* stack */,
120 int /* parentIndex */,
121 bool /* respectFrozen */)
122 {
123 }
124
125 //
126 // Unification code.
127 //
128
129 DagNode::ReturnResult
computeBaseSortForGroundSubterms()130 VariableDagNode::computeBaseSortForGroundSubterms()
131 {
132 return NONGROUND;
133 }
134
135 bool
computeSolvedForm2(DagNode * rhs,UnificationContext & solution,PendingUnificationStack & pending)136 VariableDagNode::computeSolvedForm2(DagNode* rhs, UnificationContext& solution, PendingUnificationStack& pending)
137 {
138 //
139 // In this version we only handle variable vs variable unfication and
140 // punt on everything else.
141 //
142 if (VariableDagNode* v = dynamic_cast<VariableDagNode*>(rhs))
143 {
144 VariableDagNode* lv = lastVariableInChain(solution);
145 VariableDagNode* rv = v->lastVariableInChain(solution);
146 if (lv->equal(rv))
147 return true;
148 //
149 // Need to replace one variable by the other throughout the problem. We do this
150 // virtually and must check for implicit occurs check problems.
151 //
152 // Might need to check we never map an original variable to a fresh variable.
153 //
154 DagNode* lt = solution.value(lv->index);
155 if (lt == 0)
156 return safeVirtualReplacement(lv, rv, solution, pending);
157
158 DagNode* rt = solution.value(rv->index);
159 if (rt == 0)
160 return safeVirtualReplacement(rv, lv, solution, pending);
161 //
162 // Both variables are bound.
163 //
164 return safeVirtualReplacement(lv, rv, solution, pending) && lt->computeSolvedForm(rt, solution, pending);
165 }
166 //
167 // Calling computeSolvedForm() would just kick the problem back to us if
168 // rhs is ground, since this is a variable, and this would cause an infinite recursion.
169 //
170 return rhs->computeSolvedForm2(this, solution, pending);
171 }
172
173 bool
safeVirtualReplacement(VariableDagNode * oldVar,VariableDagNode * newVar,UnificationContext & solution,PendingUnificationStack & pending)174 VariableDagNode::safeVirtualReplacement(VariableDagNode* oldVar, VariableDagNode* newVar, UnificationContext& solution, PendingUnificationStack& pending)
175 {
176 //
177 // We want to replace all occurrences of oldVar by newVar. We assume oldVar is the last
178 // variable in its chain and is unbound (or has a binding which can be ignored because the
179 // caller is dealing with it) and newVar is the last variable in its chain.
180 // We do this by binding oldVar to newVar and since whenever we access a variable,
181 // we look for the last variable in the chain, accessing oldVar will give us newVar.
182 //
183 // There is however a problem. If newVar is bound and its binding contains oldVar
184 // (or a variable equivalent to it) we generate an implicit occur check issue. We
185 // could un-solve and re-solve its binding, but if there is no occur check issue,
186 // re-solving could give us a similar variable replacement problem, also resulting in
187 // non-termination.
188 //
189 // So we check the binding of newVar to see if it contains oldVar, and only then
190 // do we unsolve it.
191 //
192 solution.unificationBind(oldVar, newVar);
193 DagNode* newBinding = solution.value(newVar->index);
194 if (newBinding == 0 || newBinding->isGround())
195 return true;
196
197 NatSet occurs;
198 newBinding->insertVariables(occurs);
199 FOR_EACH_CONST(i, NatSet, occurs)
200 {
201 if (VariableDagNode* v = dynamic_cast<VariableDagNode*>(solution.value(*i)))
202 {
203 if (v->lastVariableInChain(solution)->equal(newVar))
204 {
205 //
206 // We have an occur check issue. We unsolve newVar |-> newBinding and re-solve it.
207 //
208 solution.bind(newVar->index, 0);
209 return newBinding->computeSolvedForm2(newVar, solution, pending);
210 }
211 }
212 }
213 //
214 // No implicit occurs check issue found. Leave the binding of newVar as it was.
215 //
216 return true;
217 }
218
219 void
insertVariables2(NatSet & occurs)220 VariableDagNode::insertVariables2(NatSet& occurs)
221 {
222 occurs.insert(index);
223 }
224
225 DagNode*
instantiate2(const Substitution & substitution)226 VariableDagNode::instantiate2(const Substitution& substitution)
227 {
228 return substitution.value(index);
229 }
230
231 VariableDagNode*
lastVariableInChain(Substitution & solution)232 VariableDagNode::lastVariableInChain(Substitution& solution)
233 {
234 //
235 // If a variable has been bound to anther variable, it is notionally
236 // replaced by that variable thoughout the problem, and in particular
237 // we need chase the replacement chain and find out what variable is
238 // notionally in its place.
239 //
240 VariableDagNode* v = this;
241 for (;;)
242 {
243 DagNode* d = solution.value(v->index);
244 if (d == 0)
245 break;
246 VariableDagNode* n = dynamic_cast<VariableDagNode*>(d);
247 if (n == 0)
248 break;
249 if (v == n)
250 {
251 cerr << "variable " << (DagNode*) v << " is bound to itself in a chain starting at " << (DagNode*) this << endl;
252 abort();
253 }
254 v = n;
255 }
256 return v;
257 }
258
259 //
260 // Narrowing code.
261 //
262
263 bool
indexVariables2(NarrowingVariableInfo & indices,int baseIndex)264 VariableDagNode::indexVariables2(NarrowingVariableInfo& indices, int baseIndex)
265 {
266 index = baseIndex + indices.variable2Index(this);
267 return false;
268 }
269
270 DagNode*
instantiateWithCopies2(const Substitution &,const Vector<DagNode * > & eagerCopies)271 VariableDagNode::instantiateWithCopies2(const Substitution& /* substitution */, const Vector<DagNode*>& eagerCopies)
272 {
273 //
274 // We must be in an eager position so use the eager copy.
275 //
276 return eagerCopies[index];
277 }
278