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