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 // Code for building the constructor diagram.
25 //
26
27 bool
containsConstructor(const NatSet & state,bool & unique)28 SortTable::containsConstructor(const NatSet& state, bool& unique)
29 {
30 bool seenCtor = false;
31 bool seenNonCtor = false;
32 const NatSet::const_iterator e = state.end();
33 for (NatSet::const_iterator i = state.begin(); i != e; ++i)
34 {
35 if (opDeclarations[*i].isConstructor())
36 seenCtor = true;
37 else
38 seenNonCtor = true;
39 }
40 unique = !(seenCtor && seenNonCtor);
41 return seenCtor;
42 }
43
44 bool
partlyMoreGeneral(const OpDeclaration & subsumer,const OpDeclaration & victim,int argNr)45 SortTable::partlyMoreGeneral(const OpDeclaration& subsumer,
46 const OpDeclaration& victim,
47 int argNr)
48 {
49 const Vector<Sort*>& s = subsumer.getDomainAndRange();
50 const Vector<Sort*>& v = victim.getDomainAndRange();
51 int nrArgs = s.length() - 1;
52 for (int i = argNr; i < nrArgs; i++)
53 {
54 if (!(leq(v[i], s[i])))
55 return false;
56 }
57 return true;
58 }
59
60 bool
ctorSubsumes(const OpDeclaration & subsumer,const OpDeclaration & victim,int argNr)61 SortTable::ctorSubsumes(const OpDeclaration& subsumer,
62 const OpDeclaration& victim,
63 int argNr)
64 {
65 const Vector<Sort*>& s = subsumer.getDomainAndRange();
66 const Vector<Sort*>& v = victim.getDomainAndRange();
67 int nrArgs = s.length() - 1;
68 //
69 // Check to see that we are equal on unchecked args.
70 //
71 for (int i = argNr; i < nrArgs; i++)
72 {
73 if (v[i] != s[i])
74 return false;
75 }
76 //
77 // Check to see that we are <= on checked args.
78 //
79 bool strict = false;
80 for (int i = 0; i < argNr; i++)
81 {
82 if (v[i] != s[i])
83 {
84 if (leq(s[i], v[i]))
85 strict = true;
86 else
87 return false;
88 }
89 }
90 //
91 // If ctor status differs we need strictness for subsumption.
92 //
93 return strict || (subsumer.isConstructor() == victim.isConstructor());
94 }
95
96 void
minimizeWrtCtor(NatSet & alive,int argNr) const97 SortTable::minimizeWrtCtor(NatSet& alive, int argNr) const
98 {
99 bool seenCtor = false;
100 bool seenNonCtor = false;
101 const NatSet::const_iterator e = alive.end();
102 for (NatSet::const_iterator i = alive.begin(); i != e; ++i)
103 {
104 if (opDeclarations[*i].isConstructor())
105 seenCtor = true;
106 else
107 seenNonCtor = true;
108 }
109 if (!seenCtor)
110 alive.makeEmpty();
111 else if (!seenNonCtor)
112 {
113 //
114 // We are going to be ctor in any declaration
115 // survives so ctor subsumes ctor if it is >=
116 // on unchecked arguments.
117 //
118 int min = alive.min();
119 int max = alive.max();
120 for (int i = min; i <= max; i++)
121 {
122 if (alive.contains(i))
123 {
124 for (int j = min; j <= max; j++)
125 {
126 if (j != i &&
127 alive.contains(j) &&
128 partlyMoreGeneral(opDeclarations[i],
129 opDeclarations[j],
130 argNr))
131 alive.subtract(j);
132 }
133 }
134 }
135 }
136 else
137 {
138 //
139 // Like can subsume like by being <= on checked
140 // arguments and = on unchecked args.
141 // For ctor to subsume non-ctor and viceversa
142 // we also need strict < on at least one checked
143 // argument.
144 //
145 int min = alive.min();
146 int max = alive.max();
147 for (int i = min; i <= max; i++)
148 {
149 if (alive.contains(i))
150 {
151 for (int j = min; j <= max; j++)
152 {
153 if (j != i &&
154 alive.contains(j) &&
155 ctorSubsumes(opDeclarations[i],
156 opDeclarations[j],
157 argNr))
158 alive.subtract(j);
159 }
160 }
161 }
162 }
163 }
164
165 void
buildCtorDiagram()166 SortTable::buildCtorDiagram()
167 {
168 //
169 // Start with all op declarations alive.
170 //
171 Vector<NatSet> currentStates(1);
172 NatSet& all = currentStates[0];
173 int nrDeclarations = opDeclarations.length();
174 for (int i = nrDeclarations - 1; i >= 0; i--)
175 all.insert(i); // insert in reverse order for efficiency
176
177 if (nrArgs == 0)
178 {
179 bool unique;
180 ctorDiagram.append(containsConstructor(all, unique));
181 WarningCheck(unique, "constructor declarations for constant " << QUOTE(safeCast(Symbol*, this)) <<
182 " are inconsistant.");
183 return;
184 }
185
186 Vector<NatSet> nextStates;
187 int currentBase = 0;
188 set<int> badTerminals;
189 for (int i = 0; i < nrArgs; i++)
190 {
191 const ConnectedComponent* component = componentVector[i];
192 int nrSorts = component->nrSorts();
193 int nrCurrentStates = currentStates.length();
194
195 int nextBase = currentBase + nrSorts * nrCurrentStates;
196 ctorDiagram.resize(nextBase);
197 int nrNextSorts = (i == nrArgs - 1) ? 0 : componentVector[i + 1]->nrSorts();
198
199 for (int j = 0; j < nrSorts; j++)
200 {
201 Sort* s = component->sort(j);
202 NatSet viable;
203 for (int k = 0; k < nrDeclarations; k++)
204 {
205 if (leq(s, opDeclarations[k].getDomainAndRange()[i]))
206 viable.insert(k);
207 }
208 for (int k = 0; k < nrCurrentStates; k++)
209 {
210 NatSet nextState(viable);
211 nextState.intersect(currentStates[k]);
212 int index = currentBase + k * nrSorts + j;
213 if (nrNextSorts == 0)
214 {
215 minimizeWrtCtor(nextState, i + 1);
216 bool unique;
217 ctorDiagram[index] = containsConstructor(nextState, unique);
218 if (!unique)
219 badTerminals.insert(index);
220 }
221 else
222 {
223 minimizeWrtCtor(nextState, i + 1);
224 ctorDiagram[index] =
225 nextBase + nrNextSorts * findStateNumber(nextStates, nextState);
226 }
227 }
228 }
229 currentStates.swap(nextStates);
230 nextStates.contractTo(0);
231 currentBase = nextBase;
232 }
233 if (!(badTerminals.empty()))
234 sortErrorAnalysis(false, badTerminals);
235 }
236