1 /*
2
3 This file is part of the Maude 2 interpreter.
4
5 Copyright 1997-2003 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 S_DagNode.
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 #include "S_Theory.hh"
36
37 // interface class definitions
38 #include "term.hh"
39
40 // core class definitions
41 #include "pendingUnificationStack.hh"
42 #include "unificationContext.hh"
43
44 // variable class definitions
45 #include "variableDagNode.hh"
46
47 // S theory class definitions
48 #include "S_Symbol.hh"
49 #include "S_DagNode.hh"
50 #include "S_DagArgumentIterator.hh"
51 #include "S_ExtensionInfo.hh"
52 #include "S_Subproblem.hh"
53
S_DagNode(S_Symbol * symbol,const mpz_class & number,DagNode * arg)54 S_DagNode::S_DagNode(S_Symbol* symbol, const mpz_class& number, DagNode* arg)
55 : DagNode(symbol),
56 number(new mpz_class(number)),
57 arg(arg)
58 {
59 setCallDtor(); // need our dtor called when garbage collected to destruct number
60 }
61
~S_DagNode()62 S_DagNode::~S_DagNode()
63 {
64 delete number;
65 }
66
67 RawDagArgumentIterator*
arguments()68 S_DagNode::arguments()
69 {
70 return new S_DagArgumentIterator(arg);
71 }
72
73 size_t
getHashValue()74 S_DagNode::getHashValue()
75 {
76 return hash(symbol()->getHashValue(),
77 arg->getHashValue(),
78 mpz_tdiv_ui(number->get_mpz_t(), INT_MAX));
79 }
80
81 int
compareArguments(const DagNode * other) const82 S_DagNode::compareArguments(const DagNode* other) const
83 {
84 const S_DagNode* d = safeCast(const S_DagNode*, other);
85 int r = cmp(*number, *(d->number));
86 return (r == 0) ? arg->compare(d->arg) : r;
87 }
88
89 DagNode*
markArguments()90 S_DagNode::markArguments()
91 {
92 return arg;
93 }
94
95 DagNode*
copyEagerUptoReduced2()96 S_DagNode::copyEagerUptoReduced2()
97 {
98 S_Symbol* s = symbol();
99 DagNode* argCopy = (s->standardStrategy()) ? arg->copyEagerUptoReduced() : arg;
100 return new S_DagNode(s, *number, argCopy);
101 }
102
103 void
clearCopyPointers2()104 S_DagNode::clearCopyPointers2()
105 {
106 arg->clearCopyPointers();
107 }
108
109 void
overwriteWithClone(DagNode * old)110 S_DagNode::overwriteWithClone(DagNode* old)
111 {
112 S_DagNode* d = new(old) S_DagNode(symbol(), *number, arg);
113 d->copySetRewritingFlags(this);
114 d->setSortIndex(getSortIndex());
115 }
116
117 DagNode*
makeClone()118 S_DagNode::makeClone()
119 {
120 S_DagNode* d = new S_DagNode(symbol(), *number, arg);
121 d->copySetRewritingFlags(this);
122 d->setSortIndex(getSortIndex());
123 return d;
124 }
125
126 void
normalizeAtTop()127 S_DagNode::normalizeAtTop()
128 {
129 if (arg->symbol() == symbol())
130 {
131 S_DagNode* a = safeCast(S_DagNode*, arg);
132 *number += *(a->number);
133 arg = a->arg;
134 }
135 }
136
137 DagNode*
copyWithReplacement(int argIndex,DagNode * replacement)138 S_DagNode::copyWithReplacement(int argIndex, DagNode* replacement)
139 {
140 Assert(argIndex == 0, "bad arg index");
141 return new S_DagNode(symbol(), *number, replacement);
142 }
143
144 DagNode*
copyWithReplacement(Vector<RedexPosition> & redexStack,int first,int last)145 S_DagNode::copyWithReplacement(Vector<RedexPosition>& redexStack,
146 int first,
147 int last)
148 {
149 Assert(first == last, "nrArgs clash");
150 return new S_DagNode(symbol(), *number, redexStack[first].node());
151 }
152
153 void
stackArguments(Vector<RedexPosition> & stack,int parentIndex,bool respectFrozen)154 S_DagNode::stackArguments(Vector<RedexPosition>& stack,
155 int parentIndex,
156 bool respectFrozen)
157 {
158 if (!(respectFrozen && symbol()->getFrozen().contains(0)) &&
159 !(arg->isUnstackable()))
160 stack.append(RedexPosition(arg, parentIndex, 0));
161 }
162
163 void
partialReplace(DagNode * replacement,ExtensionInfo * extensionInfo)164 S_DagNode::partialReplace(DagNode* replacement, ExtensionInfo* extensionInfo)
165 {
166 *number = safeCast(S_ExtensionInfo*, extensionInfo)->getUnmatched();
167 arg = replacement;
168 repudiateSortInfo();
169 }
170
171 DagNode*
partialConstruct(DagNode * replacement,ExtensionInfo * extensionInfo)172 S_DagNode::partialConstruct(DagNode* replacement, ExtensionInfo* extensionInfo)
173 {
174 return new S_DagNode(symbol(),
175 safeCast(S_ExtensionInfo*, extensionInfo)->getUnmatched(),
176 replacement);
177 }
178
179 ExtensionInfo*
makeExtensionInfo()180 S_DagNode::makeExtensionInfo()
181 {
182 return new S_ExtensionInfo(this);
183 }
184
185 bool
matchVariableWithExtension(int index,const Sort * sort,Substitution &,Subproblem * & returnedSubproblem,ExtensionInfo * extensionInfo)186 S_DagNode::matchVariableWithExtension(int index,
187 const Sort* sort,
188 Substitution& /* solution */,
189 Subproblem*& returnedSubproblem,
190 ExtensionInfo* extensionInfo)
191 {
192 //
193 // Because we have not matched a S_Theory operator, we cannot put
194 // put all the S_Theory operator into the extension and therefore we
195 // pass mustMatchAtLeast = 1 rather than the default value of 0.
196 //
197 returnedSubproblem =
198 new S_Subproblem(this,
199 *number,
200 index,
201 sort,
202 safeCast(S_ExtensionInfo*, extensionInfo),
203 1);
204 return true;
205 }
206
207 //
208 // Unification code.
209 //
210
211 DagNode::ReturnResult
computeBaseSortForGroundSubterms()212 S_DagNode::computeBaseSortForGroundSubterms()
213 {
214 ReturnResult r = arg->computeBaseSortForGroundSubterms();
215 if (r == GROUND)
216 symbol()->computeBaseSort(this);
217 return r;
218 }
219
220 bool
computeSolvedForm2(DagNode * rhs,UnificationContext & solution,PendingUnificationStack & pending)221 S_DagNode::computeSolvedForm2(DagNode* rhs, UnificationContext& solution, PendingUnificationStack& pending)
222 {
223 S_Symbol* s = symbol();
224 if (s == rhs->symbol())
225 {
226 S_DagNode* rhs2 = safeCast(S_DagNode*, rhs);
227 mpz_class diff = *(rhs2->number) - *number;
228 if (diff == 0)
229 return arg->computeSolvedForm(rhs2->arg, solution, pending);
230 //
231 // Decompose by peeling the side with greatest iteration count.
232 //
233 if (diff > 0)
234 {
235 DagNode* d = new S_DagNode(s, diff, rhs2->arg);
236 if (rhs2->arg->getSortIndex() != Sort::SORT_UNKNOWN)
237 s->computeBaseSort(d);
238 return arg->computeSolvedForm(d, solution, pending);
239 }
240 DagNode* d = new S_DagNode(s, -diff, arg);
241 if (arg->getSortIndex() != Sort::SORT_UNKNOWN)
242 s->computeBaseSort(d);
243 return rhs2->arg->computeSolvedForm(d, solution, pending);
244 }
245 if (VariableDagNode* v = dynamic_cast<VariableDagNode*>(rhs))
246 {
247 //
248 // Get representative variable.
249 //
250 VariableDagNode* r = v->lastVariableInChain(solution);
251 if (DagNode* value = solution.value(r->getIndex()))
252 return computeSolvedForm2(value, solution, pending);
253 //
254 // We need to bind the variable to our purified form.
255 //
256 // We assume we are in normal form - thus our subject can only be
257 // an alien or a variable, and only aliens need to be variable abstracted.
258 //
259 S_DagNode* purified;
260 if (VariableDagNode* a = dynamic_cast<VariableDagNode*>(arg))
261 {
262 //
263 // Already pure but need to do an occurs check.
264 //
265 if (a->lastVariableInChain(solution)->equal(r))
266 return false; // occurs check fail
267 purified = this;
268 }
269 else
270 {
271 //
272 // Abstract away alien.
273 //
274 VariableDagNode* abstractionVariable = solution.makeFreshVariable(s->domainComponent(0));
275 //
276 // solution.unificationBind(abstractionVariable, arg) not safe since arg might be impure.
277 //
278 arg->computeSolvedForm(abstractionVariable, solution, pending);
279 purified = new S_DagNode(s, *number, abstractionVariable);
280 }
281 solution.unificationBind(r, purified);
282 return true;
283 }
284 return pending.resolveTheoryClash(this, rhs);
285 }
286
287 void
insertVariables2(NatSet & occurs)288 S_DagNode::insertVariables2(NatSet& occurs)
289 {
290 arg->insertVariables(occurs);
291 }
292
293 DagNode*
instantiate2(const Substitution & substitution)294 S_DagNode::instantiate2(const Substitution& substitution)
295 {
296 if (DagNode* n = arg->instantiate(substitution))
297 {
298 mpz_class num = *number;
299 S_Symbol* s = symbol();
300 if (s == n->symbol())
301 {
302 //
303 // Our argument instantiated into our theory so we need
304 // to do theory normalization.
305 //
306 S_DagNode* t = safeCast(S_DagNode*, n);
307 num += *(t->number);
308 n = t->arg;
309 }
310 DagNode* d = new S_DagNode(s, num, n);
311 if (n->isGround())
312 {
313 s->computeBaseSort(d);
314 d->setGround();
315 }
316 return d;
317 }
318 return 0;
319 }
320
321 //
322 // Narrowing code.
323 //
324
325 DagNode*
instantiateWithReplacement(const Substitution &,const Vector<DagNode * > &,int argIndex,DagNode * newDag)326 S_DagNode::instantiateWithReplacement(const Substitution& /* substitution */, const Vector<DagNode*>& /* eagerCopies */, int argIndex, DagNode* newDag)
327 {
328 Assert(argIndex == 0, "bad arg index");
329 return new S_DagNode(symbol(), *number, newDag);
330 }
331
332 DagNode*
instantiateWithCopies2(const Substitution & substitution,const Vector<DagNode * > & eagerCopies)333 S_DagNode::instantiateWithCopies2(const Substitution& substitution, const Vector<DagNode*>& eagerCopies)
334 {
335 S_Symbol* s = symbol();
336 DagNode* n = s->eagerArgument(0) ?
337 arg->instantiateWithCopies(substitution, eagerCopies) :
338 arg->instantiate(substitution);
339 if (n != 0)
340 {
341 mpz_class num = *number;
342 if (s == n->symbol())
343 {
344 //
345 // Our argument instantiated into our theory so we need
346 // to do theory normalization.
347 //
348 S_DagNode* t = safeCast(S_DagNode*, n);
349 num += *(t->number);
350 n = t->arg;
351 }
352 DagNode* d = new S_DagNode(s, num, n);
353 if (n->isGround())
354 {
355 s->computeBaseSort(d);
356 d->setGround();
357 }
358 return d;
359 }
360 return 0;
361 }
362
363