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 base class Symbol.
25 //
26
27 // utility stuff
28 #include "macros.hh"
29 #include "vector.hh"
30 #include "indent.hh"
31
32 // forward declarations
33 #include "interface.hh"
34 #include "core.hh"
35 #include "variable.hh"
36 #include "fullCompiler.hh"
37
38 // interface class definitions
39 #include "symbol.hh"
40 #include "dagNode.hh"
41 #include "term.hh"
42
43 // core class definitions
44 #include "argumentIterator.hh"
45 #include "dagArgumentIterator.hh"
46 #include "equation.hh"
47 #include "rule.hh"
48 #include "sortConstraint.hh"
49
50 // variable class definitions
51 #include "variableSymbol.hh"
52
53 // full compiler class definitions
54 #include "compilationContext.hh"
55
56 int Symbol::symbolCount = 0;
57 const Vector<DagNode*> Symbol::noArgs; // constant empty vector
58
Symbol(int id,int arity,bool memoFlag)59 Symbol::Symbol(int id, int arity, bool memoFlag)
60 : NamedEntity(id),
61 SortTable(arity),
62 MemoTable(memoFlag),
63 orderInt(symbolCount++ | (arity << 24))
64 {
65 uniqueSortIndex = 0;
66 matchIndex = 0;
67 }
68
~Symbol()69 Symbol::~Symbol()
70 {
71 }
72
73 void
slowComputeTrueSort(DagNode * subject,RewritingContext & context)74 Symbol::slowComputeTrueSort(DagNode* subject, RewritingContext& context)
75 {
76 if (subject->getSortIndex() == Sort::SORT_UNKNOWN)
77 {
78 computeBaseSort(subject);
79 constrainToSmallerSort(subject, context);
80 }
81 }
82
83 bool
mightMatchPattern(Term * pattern)84 Symbol::mightMatchPattern(Term* pattern)
85 {
86 if (mightMatchSymbol(pattern->symbol()))
87 return true;
88 const PointerSet& cs = pattern->collapseSymbols();
89 int cardinality = cs.cardinality();
90 for (int i = 0; i < cardinality; i++)
91 {
92 if (mightMatchSymbol(static_cast<Symbol*>(cs.index2Pointer(i))))
93 return true;
94 }
95 return false;
96 }
97
98 bool
mightMatchSymbol(Symbol * symbol)99 Symbol::mightMatchSymbol(Symbol* symbol)
100 {
101 if (symbol == this)
102 return true;
103 if (VariableSymbol* vs = dynamic_cast<VariableSymbol*>(symbol))
104 {
105 Sort* s = vs->getSort();
106 if (rangeComponent() == s->component())
107 {
108 if (specialSortHandling())
109 return true; // can't tell anything about a symbol with special sort handling
110 if (!safeToInspectSortConstraints())
111 return true; // uninspected sort constraint may lower our symbols lowest sort
112 const Vector<OpDeclaration>& opDeclarations = getOpDeclarations();
113 int nrDeclarations = opDeclarations.length();
114 int nrArgs = arity();
115 for (int i = 0; i < nrDeclarations; i++)
116 {
117 if (leq(opDeclarations[i].getDomainAndRange()[nrArgs], s))
118 return true;
119 }
120 const Vector<SortConstraint*>& sortConstraints = getSortConstraints();
121 int nrSortConstraints = sortConstraints.length();
122 for (int i = 0; i < nrSortConstraints; i++)
123 {
124 if (leq(sortConstraints[i]->getSort(), s))
125 return true;
126 }
127 }
128 }
129 return false;
130 }
131
132 bool
acceptSortConstraint(SortConstraint * sortConstraint)133 Symbol::acceptSortConstraint(SortConstraint* sortConstraint)
134 {
135 return mightMatchPattern(sortConstraint->getLhs());
136 }
137
138 bool
acceptEquation(Equation * equation)139 Symbol::acceptEquation(Equation* equation)
140 {
141 return mightMatchPattern(equation->getLhs());
142 }
143
144 bool
acceptRule(Rule * rule)145 Symbol::acceptRule(Rule* rule)
146 {
147 return mightMatchPattern(rule->getLhs());
148 }
149
150 void
fillInSortInfo(Term * subject)151 Symbol::fillInSortInfo(Term* subject)
152 {
153 Assert(this == subject->symbol(), "Bad Symbol");
154 ConnectedComponent* component = rangeComponent(); // should be const
155 Assert(component != 0, "couldn't get component");
156
157 int nrArgs = arity();
158 if (nrArgs == 0)
159 {
160 subject->setSortInfo(component, traverse(0, 0)); // HACK
161 return;
162 }
163
164 int step = 0;
165 #ifndef NO_ASSERT
166 int nrArgsSeen = 0;
167 #endif
168 for (ArgumentIterator a(*subject); a.valid(); a.next())
169 {
170 Term* t = a.argument();
171 t->symbol()->fillInSortInfo(t);
172 Assert(t->getComponent() == domainComponent(nrArgsSeen),
173 "component error on arg " << nrArgsSeen <<
174 " while computing sort of " << subject);
175 step = traverse(step, t->getSortIndex());
176 #ifndef NO_ASSERT
177 ++nrArgsSeen;
178 #endif
179 }
180 Assert(nrArgsSeen == nrArgs, "bad # of args for op");
181 subject->setSortInfo(component, step);
182 }
183
184 bool
interSymbolPass()185 Symbol::interSymbolPass()
186 {
187 return false;
188 }
189
190 void
postInterSymbolPass()191 Symbol::postInterSymbolPass()
192 {
193 }
194
195 void
postOpDeclarationPass()196 Symbol::postOpDeclarationPass()
197 {
198 }
199
200 /*
201 Term*
202 Symbol::termify(DagNode* dagNode)
203 {
204 Vector<Term*> args;
205
206 for (DagArgumentIterator a(*dagNode); a.valid(); a.next())
207 {
208 DagNode* d = a.argument();
209 args.append(d->symbol()->termify(d));
210 }
211 return makeTerm(args);
212 }
213 */
214
215 void
finalizeSortInfo()216 Symbol::finalizeSortInfo()
217 {
218 //
219 // If a symbol has sort constraints we leave uniqueSortIndex = 0 for slowest, most general handling.
220 // Otherwise we check if it can produces a unique sort and set uniqueSortIndex to the index of this sort if so.
221 // If neither case applies we set uniqueSortIndex = -1, to run fast, theory dependent case.
222 //
223 if (sortConstraintFree())
224 {
225 Sort* s = getSingleNonErrorSort();
226 uniqueSortIndex = (s != 0 && !(canProduceErrorSort())) ? s->index() : -1;
227 }
228 }
229
230 Instruction*
generateFinalInstruction(const Vector<int> &)231 Symbol::generateFinalInstruction(const Vector<int>& /* argumentSlots */)
232 {
233 return 0;
234 }
235
236 Instruction*
generateInstruction(int,const Vector<int> &,Instruction *)237 Symbol::generateInstruction(int /* destination */, const Vector<int>& /* argumentSlots */, Instruction* /* nextInstruction */)
238 {
239 return 0;
240 }
241
242 void
stackMachinePostProcess()243 Symbol::stackMachinePostProcess()
244 {
245 }
246
247 void
reset()248 Symbol::reset()
249 {
250 resetEachEquation();
251 resetEachRule();
252 }
253
254 bool
rangeSortNeverLeqThan(Sort * sort)255 Symbol::rangeSortNeverLeqThan(Sort* sort)
256 {
257 //
258 // Check to see that our range sort will never be less than or equal to
259 // given sort; Equivalently a variable with given sort can never take a
260 // term headed by us.
261 //
262 int nrArgs = arity();
263 const Vector<OpDeclaration>& opDecls = getOpDeclarations();
264 int nrOpDecls = opDecls.length();
265 for (int i = 0; i < nrOpDecls; i++)
266 {
267 if (leq(opDecls[i].getDomainAndRange()[nrArgs], sort))
268 return false;
269 }
270 const Vector<SortConstraint*>& sortConstraints = getSortConstraints();
271 int nrSortConstraints = sortConstraints.length();
272 for (int i = 0; i < nrSortConstraints; i++)
273 {
274 if (leq(sortConstraints[i]->getSort(), sort))
275 return false;
276 }
277 return true;
278 }
279
280 bool
rangeSortAlwaysLeqThan(Sort * sort)281 Symbol::rangeSortAlwaysLeqThan(Sort* sort)
282 {
283 //
284 // Check to see that our range sort will always be less than or equal to
285 // given sort (except if it is in the error sort); Equivalently a variable
286 // with given sort can always take a term headed by us unless it is in the
287 // error sort.
288 //
289 int nrArgs = arity();
290 const Vector<OpDeclaration>& opDecls = getOpDeclarations();
291 int nrOpDecls = opDecls.length();
292 for (int i = 0; i < nrOpDecls; i++)
293 {
294 if (!leq(opDecls[i].getDomainAndRange()[nrArgs], sort))
295 return false;
296 }
297 return true;
298 }
299
300 bool
domainSortAlwaysLeqThan(Sort * sort,int argNr)301 Symbol::domainSortAlwaysLeqThan(Sort* sort, int argNr)
302 {
303 //
304 // Check that any sort we could take in our argNr position and not end up
305 // in the error sort is less or equal to the given sort.
306 // The current definition will be seriously incorrect if sort constraints
307 // are allowed to terms out of the error sort in the future.
308 //
309 const Vector<OpDeclaration>& opDecls = getOpDeclarations();
310 int nrOpDecls = opDecls.length();
311 for (int i = 0; i < nrOpDecls; i++)
312 {
313 if (!leq(opDecls[i].getDomainAndRange()[argNr], sort))
314 return false;
315 }
316 return true;
317 }
318
319 void
computePossibleDomainSorts(const NatSet & rangeSorts,Vector<NatSet> & domainSorts)320 Symbol::computePossibleDomainSorts(const NatSet& rangeSorts,
321 Vector<NatSet>& domainSorts)
322 {
323 Assert(!(rangeSorts.empty()), "shouldn't be empty");
324 //
325 // We compute the set of sorts that the specified argument can possibly have
326 // given that the range sort must be <= one of the specified range sorts.
327 // We are conservative in that we may generate a larger set of domain sorts
328 // than strictly necessary.
329 //
330 int nrArgs = arity();
331 domainSorts.resize(nrArgs);
332 if (specialSortHandling() ||
333 !safeToInspectSortConstraints() ||
334 rangeSorts.contains(Sort::KIND))
335 {
336 //
337 // We can't safely compute anything in these cases so
338 // return the complete set of domain sorts.
339 //
340 for (int i = 0; i < nrArgs; i++)
341 domainSorts[i] = domainComponent(i)->sort(Sort::KIND)->getLeqSorts();
342 return;
343 }
344 NatSet allPossibleRangeSorts;
345 {
346 //
347 // First throw in all sorts that are less or equal to given range sorts.
348 //
349 const ConnectedComponent* rc = rangeComponent();
350 const NatSet::const_iterator e = rangeSorts.end();
351 for (NatSet::const_iterator i = rangeSorts.begin(); i != e; ++i)
352 allPossibleRangeSorts.insert(rc->sort(*i)->getLeqSorts());
353 }
354 {
355 //
356 // Now do a fixed point computation to see if we can get down from
357 // other sorts to or below our given range sorts via a sort constraint.
358 //
359 const Vector<SortConstraint*>& sortConstraints = getSortConstraints();
360 int nrSortConstraints = sortConstraints.length();
361 bool changed;
362 do
363 {
364 changed = false;
365 for (int i = 0; i < nrSortConstraints; i++)
366 {
367 SortConstraint* sc = sortConstraints[i];
368 if (allPossibleRangeSorts.contains(sc->getSort()->index()))
369 {
370 const NatSet& fromSorts = sc->getLhs()->getSort()->getLeqSorts();
371 if (fromSorts.contains(Sort::KIND))
372 {
373 //
374 // A sort constraint can pull us out of the kind!
375 //
376 for (int i = 0; i < nrArgs; i++)
377 domainSorts[i] = domainComponent(i)->sort(Sort::KIND)->getLeqSorts();
378 return;
379 }
380 if (!(allPossibleRangeSorts.contains(fromSorts)))
381 {
382 allPossibleRangeSorts.insert(fromSorts);
383 changed = true;
384 }
385 }
386 }
387 }
388 while (changed);
389 }
390 Assert(!(allPossibleRangeSorts.contains(Sort::KIND)),
391 "shouldn't contain kind");
392 {
393 //
394 // Now examine our declarations to see what domain sorts are possible
395 // in each argument position.
396 //
397 for (int i = 0; i < nrArgs; i++)
398 domainSorts[i].clear();
399
400 const Vector<OpDeclaration>& opDeclarations = getOpDeclarations();
401 int nrDeclarations = opDeclarations.length();
402 for (int i = 0; i < nrDeclarations; i++)
403 {
404 const Vector<Sort*>& domainAndRange = opDeclarations[i].getDomainAndRange();
405 if (allPossibleRangeSorts.contains(domainAndRange[nrArgs]->index()))
406 {
407 for (int j = 0; j < nrArgs; j++)
408 domainSorts[j].insert(domainAndRange[j]->getLeqSorts());
409 }
410 }
411 }
412 }
413
414 bool
attachData(const Vector<Sort * > &,const char * purpose,const Vector<const char * > &)415 Symbol::attachData(const Vector<Sort*>& /* opDeclaration */,
416 const char* purpose,
417 const Vector<const char*>& /* data */)
418 {
419 IssueWarning(*this <<": failed to attach id-hook " << QUOTE(purpose) <<
420 " to " << QUOTE(this) << '.');
421 return false;
422 }
423
424 bool
attachSymbol(const char * purpose,Symbol * symbol)425 Symbol::attachSymbol(const char* purpose, Symbol* symbol)
426 {
427 IssueWarning(*this <<": failed to attach op-hook " << QUOTE(purpose) <<
428 ' ' << QUOTE(symbol) << " to " << QUOTE(this) << '.');
429 return false;
430 }
431
432 bool
attachTerm(const char * purpose,Term * term)433 Symbol::attachTerm(const char* purpose, Term* term)
434 {
435 IssueWarning(*this <<": failed to attach term-hook " << QUOTE(purpose) <<
436 ' ' << QUOTE(term) << " to " << QUOTE(this) << '.');
437 term->deepSelfDestruct();
438 return false;
439 }
440
441 void
copyAttachments(Symbol *,SymbolMap *)442 Symbol::copyAttachments(Symbol* /* original */, SymbolMap* /* map */)
443 {
444 }
445
446 void
getDataAttachments(const Vector<Sort * > &,Vector<const char * > &,Vector<Vector<const char * >> &)447 Symbol::getDataAttachments(const Vector<Sort*>& /* opDeclaration */,
448 Vector<const char*>& /* purposes */,
449 Vector<Vector<const char*> >& /* data */)
450 {
451 }
452
453 void
getSymbolAttachments(Vector<const char * > &,Vector<Symbol * > &)454 Symbol::getSymbolAttachments(Vector<const char*>& /* purposes */,
455 Vector<Symbol*>& /* symbols */)
456 {
457 }
458
459 void
getTermAttachments(Vector<const char * > &,Vector<Term * > &)460 Symbol::getTermAttachments(Vector<const char*>& /* purposes */,
461 Vector<Term*>& /* terms */)
462 {
463 }
464
465 bool
isConstructor(DagNode * subject)466 Symbol::isConstructor(DagNode* subject)
467 {
468 if (specialSortHandling())
469 return false; // HACK
470
471 switch (getCtorStatus())
472 {
473 case SortTable::IS_CTOR:
474 return true;
475 case SortTable::IS_COMPLEX:
476 {
477 if (arity() == 0)
478 return ctorTraverse(0, 0); // HACK
479
480 int state = 0;
481 for (DagArgumentIterator a(*subject); a.valid(); a.next())
482 {
483 int t = a.argument()->getSortIndex();
484 Assert(t != Sort::SORT_UNKNOWN, "Unknown sort");
485 state = ctorTraverse(state, t);
486 }
487 return state;
488 }
489 default:
490 break;
491 }
492 return false;
493 }
494
495 //
496 // Putting this stuff here rather than the header file avoids gcc creating separate instances
497 // for derived classes tht don't define their own versions.
498 //
499
500 bool
canResolveTheoryClash()501 Symbol::canResolveTheoryClash()
502 {
503 //
504 // The default is that we can't resolve theory clashes.
505 //
506 return false;
507 }
508
509 UnificationSubproblem*
makeUnificationSubproblem()510 Symbol::makeUnificationSubproblem()
511 {
512 CantHappen("Not implemented"); return 0;
513 }
514
515 int
unificationPriority() const516 Symbol::unificationPriority() const
517 {
518 return 100;
519 }
520
521 #ifdef COMPILER
522 void
fullCompile(CompilationContext & context,bool inLine) const523 Symbol::fullCompile(CompilationContext& context, bool inLine) const
524 {
525 context.beginNewFunction();
526 #ifdef ANNOTATE
527 context.body() << "// " << this << '\n';
528 #endif
529 int nrArgs = arity();
530 int index = getIndexWithinModule();
531 //
532 // Generate forward decl for C++ function.
533 //
534 context.head() << "Node* f" << index << '(';
535 for (int i = 0; i < nrArgs; i++)
536 {
537 if (i != 0)
538 context.head() << ", ";
539 context.head() << "Node*";
540 }
541 context.head() << ");\n";
542 //
543 // Generate C++ function.
544 //
545 if (inLine)
546 context.body() << "inline ";
547 context.body() << "Node*\nf" << index << '(';
548 for (int i = 0; i < nrArgs; i++)
549 {
550 if (i != 0)
551 context.body() << ", ";
552 context.body() << "Node* a" << i;
553 }
554 context.body() << ")\n{\n F" << index << ";\n";
555 generateCode(context);
556 context.body() << "}\n\n";
557 //
558 // Generate #define for start label and/or safe slots if needed.
559 //
560 context.head() << "#define F" << getIndexWithinModule();
561 if (context.isTailRecursive())
562 context.head() << "\tstart:";
563 int maxSafe = context.getNrSafeSlots();
564 if (maxSafe > 0)
565 context.head() << "\tLink safe[" << maxSafe + 2 << ']';
566 context.head() << '\n';
567 }
568
569 void
generateCode(CompilationContext & context) const570 Symbol::generateCode(CompilationContext& context) const
571 {
572 context.body() << " // not implemented\n return 0;\n";
573 }
574 #endif
575
576 #ifdef DUMP
577 void
dump(ostream & s,int indentLevel)578 Symbol::dump(ostream& s, int indentLevel)
579 {
580 s << Indent(indentLevel) << "Dumping Symbol: \"" << this << "\"\n";
581 dumpSortDiagram(s, indentLevel);
582 dumpEquationTable(s, indentLevel);
583 }
584 #endif
585