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 to move operator declarations down from meta-level to object level.
25 //
26 
27 bool
downOpDecls(DagNode * metaOpDecls,MetaModule * m)28 MetaLevel::downOpDecls(DagNode* metaOpDecls, MetaModule* m)
29 {
30   Symbol* mo = metaOpDecls->symbol();
31   if (mo == opDeclSetSymbol)
32     {
33       for (DagArgumentIterator i(metaOpDecls); i.valid(); i.next())
34 	{
35 	  if (!downOpDecl(i.argument(), m))
36 	    return false;
37 	}
38     }
39   else if (mo != emptyOpDeclSetSymbol)
40     return downOpDecl(metaOpDecls, m);
41   return true;
42 }
43 
44 bool
downPolymorphTypeList(DagNode * metaTypeList,MixfixModule * m,const NatSet & polyArgs,Vector<Sort * > & typeList)45 MetaLevel::downPolymorphTypeList(DagNode* metaTypeList,
46 				 MixfixModule* m,
47 				 const NatSet& polyArgs,
48 				 Vector<Sort*>& typeList)
49 {
50   typeList.clear();
51   Symbol* mt = metaTypeList->symbol();
52   Sort* t;
53   if (mt == qidListSymbol)
54     {
55       int pos = 1;
56       for (DagArgumentIterator i(metaTypeList); i.valid(); i.next(), pos++)
57 	{
58 	  if (!(polyArgs.contains(pos)))
59 	    {
60 	      if (!downType(i.argument(), m, t))
61 		return false;
62 	      typeList.append(t);
63 	    }
64 	  else
65 	    typeList.append(0);
66 	}
67       return polyArgs.max() < pos;
68     }
69   if (mt == nilQidListSymbol)
70     return polyArgs.max() <= 0;
71   if (!(polyArgs.contains(1)))
72     {
73       if (!downType(metaTypeList, m, t))
74 	return false;
75       typeList.append(t);
76     }
77   else
78     typeList.append(0);
79   return polyArgs.max() <= 1;
80 }
81 
82 bool
downOpDecl(DagNode * metaOpDecl,MetaModule * m)83 MetaLevel::downOpDecl(DagNode* metaOpDecl, MetaModule* m)
84 {
85   if (metaOpDecl->symbol() == opDeclSymbol)
86     {
87       int name;
88       static Vector<Sort*> domainAndRange;
89       Sort* range;
90       AttributeInfo ai;
91       FreeDagNode* f = safeCast(FreeDagNode*, metaOpDecl);
92       if (downQid(f->getArgument(0), name) && downAttrSet(f->getArgument(3), ai))
93 	{
94 	  Token prefixName;
95 	  prefixName.tokenize(name, FileTable::META_LEVEL_CREATED);
96 	  DebugAdvisory("prefix name is " << prefixName);
97 	  if (ai.symbolType.hasFlag(SymbolType::POLY))
98 	    {
99 	      if (!downPolymorphTypeList(f->getArgument(1), m, ai.polyArgs, domainAndRange))
100 		goto fail;
101 	      if (ai.polyArgs.contains(0))
102 		domainAndRange.append(0);
103 	      else
104 		{
105 		  Sort* t;
106 		  if (!downType(f->getArgument(2), m, t))
107 		    goto fail;
108 		  domainAndRange.append(t);
109 		}
110 	      int polymorphIndex = m->addPolymorph(prefixName,
111 						   domainAndRange,
112 						   ai.symbolType,
113 						   ai.strategy,
114 						   ai.frozen,
115 						   ai.prec,
116 						   ai.gather,
117 						   ai.format,
118 						   ai.metadata);
119 	      m->addComplexSymbol(POLYMORPH, polymorphIndex, ai.identity, ai.fixUpInfo, domainAndRange);
120 	    }
121 	  else
122 	    {
123 	      if (downTypeList(f->getArgument(1), m, domainAndRange) &&
124 		  downType(f->getArgument(2), m, range))
125 		{
126 		  domainAndRange.append(range);
127 		  bool originator;
128 		  Symbol* symbol = m->addOpDeclaration(prefixName,
129 						       domainAndRange,
130 						       ai.symbolType,
131 						       ai.strategy,
132 						       ai.frozen,
133 						       ai.prec,
134 						       ai.gather,
135 						       ai.format,
136 						       ai.metadata,
137 						       originator);
138 		  if (m->parameterDeclared(symbol))
139 		    {
140 		      IssueWarning("operator declaration for operation " << QUOTE(prefixName) <<
141 				   " subsort overloads an operator of the same name from a parameter.");
142 		      return false;
143 		    }
144 
145 		  if (ai.symbolType.getBasicType() == SymbolType::BUBBLE)
146 		    {
147 		      int bubbleSpecIndex;
148 		      if (!downBubbleSpec(ai.fixUpInfo, m, symbol, bubbleSpecIndex))
149 			return false;
150 		      m->addComplexSymbol(BUBBLE, bubbleSpecIndex, ai.identity, ai.fixUpInfo);
151 		    }
152 		  else if (ai.identity != 0 || ai.fixUpInfo != 0)
153 		    {
154 		      m->addComplexSymbol(REGULAR_SYMBOL,
155 					  symbol->getIndexWithinModule(),
156 					  ai.identity,
157 					  ai.fixUpInfo,
158 					  domainAndRange);
159 		    }
160 		}
161 	      else
162 		goto fail;
163 	    }
164 	  return true;
165 	}
166     }
167  fail:
168   IssueAdvisory("bad operator declaration " << QUOTE(metaOpDecl) <<
169 		" in meta-module " << QUOTE(m) << '.');
170   return false;
171 }
172 
173 bool
downBubbleSpec(DagNode * metaBubbleSpec,MetaModule * m,Symbol * topSymbol,int & bubbleSpecIndex)174 MetaLevel::downBubbleSpec(DagNode* metaBubbleSpec,
175 			  MetaModule* m,
176 			  Symbol* topSymbol,
177 			  int& bubbleSpecIndex)
178 {
179   Symbol* mb = metaBubbleSpec->symbol();
180   if (mb != hookListSymbol)
181     return false;
182   DagArgumentIterator i(metaBubbleSpec);
183   if (!(i.valid()))
184     return false;
185   DagNode* metaIdHook = i.argument();
186   if (metaIdHook->symbol() != idHookSymbol)
187     return false;
188   FreeDagNode* f = safeCast(FreeDagNode*, metaIdHook);
189   Vector<int> args;
190   if (!downQidList(f->getArgument(1), args))
191     return false;
192   int min = 1;
193   int max = -1;
194   int leftParen = NONE;
195   int rightParen = NONE;
196   Vector<int> excludedTokens;
197   int nrArgs = args.length();
198   if (nrArgs > 0)
199     {
200       min = atoi(Token::name(args[0]));
201       if (nrArgs > 1)
202 	{
203 	  max = atoi(Token::name(args[1]));
204 	  if (nrArgs > 3)
205 	    {
206 	      leftParen = args[2];
207 	      const char* t = Token::name(leftParen);
208 	      if (t[0] == '`')
209 		leftParen = Token::encode(t + 1);
210 	      rightParen = args[3];
211 	      t = Token::name(rightParen);
212 	      if (t[0] == '`')
213 		rightParen = Token::encode(t + 1);
214 	    }
215 	}
216     }
217   for (i.next(); i.valid(); i.next())
218     {
219       FreeDagNode* f = safeCast(FreeDagNode*, i.argument());
220       if (f->symbol() == idHookSymbol)
221 	{
222 	  Vector<int> tokens;
223 	  int id;
224 	  if (!downQid(f->getArgument(0), id) ||
225 	      !downQidList(f->getArgument(1), tokens))
226 	    return false;
227 	  if (id == Token::encode("Exclude"))
228 	    {
229 	      excludedTokens = tokens;
230 	      int nrTokens = excludedTokens.length();
231 	      for (int j = 0; j < nrTokens; j++)
232 		{
233 		  const char* t = Token::name(excludedTokens[j]);
234 		  if (t[0] == '`')
235 		    excludedTokens[j] = Token::encode(t + 1);
236 		}
237 	    }
238 	}
239     }
240   bubbleSpecIndex = m->addBubbleSpec(topSymbol, min, max, leftParen, rightParen, excludedTokens);
241   return true;
242 }
243 
244 bool
downAttrSet(DagNode * metaAttrSet,AttributeInfo & ai)245 MetaLevel::downAttrSet(DagNode* metaAttrSet, AttributeInfo& ai)
246 {
247   Symbol* ma = metaAttrSet->symbol();
248   if (ma == attrSetSymbol)
249     {
250       for (DagArgumentIterator i(metaAttrSet); i.valid(); i.next())
251 	{
252 	  if (!downAttr(i.argument(), ai))
253 	    return false;
254 	}
255       }
256   else if (ma != emptyAttrSetSymbol)
257     return downAttr(metaAttrSet, ai);
258   return true;
259 }
260 
261 bool
downAttr(DagNode * metaAttr,AttributeInfo & ai)262 MetaLevel::downAttr(DagNode* metaAttr, AttributeInfo& ai)
263 {
264   Symbol* ma = metaAttr->symbol();
265   if (ma == assocSymbol)
266     ai.symbolType.setFlags(SymbolType::ASSOC);
267   else if (ma == commSymbol)
268     ai.symbolType.setFlags(SymbolType::COMM);
269   else if (ma == idemSymbol)
270     ai.symbolType.setFlags(SymbolType::IDEM);
271   else if (ma == iterSymbol)
272     ai.symbolType.setFlags(SymbolType::ITER);
273   else if (ma == stratSymbol)
274     {
275       if (!downNatList(safeCast(FreeDagNode*, metaAttr)->getArgument(0), ai.strategy))
276 	return false;
277     }
278   else if (ma == memoSymbol)
279     ai.symbolType.setFlags(SymbolType::MEMO);
280   else if (ma == precSymbol)
281     {
282       if (!(succSymbol->getSignedInt(safeCast(FreeDagNode*, metaAttr)->getArgument(0), ai.prec)))
283 	return false;
284       ai.symbolType.setFlags(SymbolType::PREC);
285     }
286   else if (ma == gatherSymbol)
287     {
288       if (!downQidList(safeCast(FreeDagNode*, metaAttr)->getArgument(0), ai.gather))
289 	return false;
290       int gatherLength = ai.gather.length();
291       for (int i = 0; i < gatherLength; i++)
292 	{
293 	  const char* string = Token::name(ai.gather[i]);
294 	  if (string[0] != '\0' && string[1] == '\0')
295 	    {
296 	      switch(string[0])
297 		{
298 		case '&':
299 		  ai.gather[i] = MixfixModule::GATHER_AMP;
300 		  continue;
301 		case 'E':
302 		  ai.gather[i] = MixfixModule::GATHER_E;
303 		  continue;
304 		case 'e':
305 		  ai.gather[i] = MixfixModule::GATHER_e;
306 		  continue;
307 		}
308 	    }
309 	  IssueAdvisory("bad value " << QUOTE(string) <<
310 			" in gather attribute at metalevel.");
311 	  return false;
312 	}
313       ai.symbolType.setFlags(SymbolType::GATHER);
314     }
315   else if (ma == formatSymbol)
316     {
317       if (!downQidList(safeCast(FreeDagNode*, metaAttr)->getArgument(0), ai.format))
318 	return false;
319       int formatLength = ai.format.length();
320       for (int i = 0; i < formatLength; i++)
321 	{
322 	  const char* str = Token::name(ai.format[i]);
323 	  if (!(SyntacticPreModule::checkFormatString(str)))
324 	    {
325 	      IssueAdvisory("bad value " << QUOTE(str) <<
326 			    " in format attribute at metalevel.");
327 	      return false;
328 	    }
329 	}
330       ai.symbolType.setFlags(SymbolType::FORMAT);
331     }
332   else if (ma == ctorSymbol)
333     ai.symbolType.setFlags(SymbolType::CTOR);
334   else if (ma == configSymbol)
335     ai.symbolType.setFlags(SymbolType::CONFIG);
336   else if (ma == objectSymbol)
337     ai.symbolType.setFlags(SymbolType::OBJECT);
338   else if (ma == msgSymbol)
339     ai.symbolType.setFlags(SymbolType::MESSAGE);
340   else if (ma == frozenSymbol)
341     {
342       Vector<int> frozenList;
343       if (!downNatList(safeCast(FreeDagNode*, metaAttr)->getArgument(0), frozenList))
344 	return false;
345       ai.symbolType.setFlags(SymbolType::FROZEN);
346       int nrFrozenArgs = frozenList.length();
347       for (int i = 0; i < nrFrozenArgs; i++)
348 	ai.frozen.insert(frozenList[i] - 1);  // FIX: NEED TO VALIDATE
349     }
350   else if (ma == polySymbol)
351     {
352       Vector<int> polyList;
353       if (!downNatList(safeCast(FreeDagNode*, metaAttr)->getArgument(0), polyList))
354 	return false;
355       ai.symbolType.setFlags(SymbolType::POLY);
356       int nrPolyArgs = polyList.length();
357       for (int i = 0; i < nrPolyArgs; i++)
358 	ai.polyArgs.insert(polyList[i]);  // FIX: NEED TO VALIDATE; maybe downNatSet?
359     }
360   else if (ma == metadataSymbol)
361     {
362        DagNode* metaStr = safeCast(FreeDagNode*, metaAttr)->getArgument(0);
363        if (metaStr->symbol() != stringSymbol)
364 	 return false;
365        string str;
366        Token::ropeToString(safeCast(StringDagNode*, metaStr)->getValue(), str);
367        ai.metadata = Token::encode(str.c_str());
368     }
369   else if (ma == specialSymbol)
370     {
371       ai.fixUpInfo = safeCast(FreeDagNode*, metaAttr)->getArgument(0);
372       checkHookList(ai.fixUpInfo, ai.symbolType);
373     }
374   else
375     {
376       if (ma == leftIdSymbol)
377 	ai.symbolType.setFlags(SymbolType::LEFT_ID);
378       else if (ma == rightIdSymbol)
379 	ai.symbolType.setFlags(SymbolType::RIGHT_ID);
380       else if (ma == idSymbol)
381 	ai.symbolType.setFlags(SymbolType::LEFT_ID | SymbolType::RIGHT_ID);
382       else
383 	return false;
384       ai.identity = safeCast(FreeDagNode*, metaAttr)->getArgument(0);
385     }
386   return true;
387 }
388 
389 void
checkHookList(DagNode * metaHookList,SymbolType & symbolType)390 MetaLevel::checkHookList(DagNode* metaHookList, SymbolType& symbolType)
391 {
392   if (metaHookList->symbol() == hookListSymbol)
393     {
394       for (DagArgumentIterator i(metaHookList); i.valid(); i.next())
395 	checkHook(i.argument(), symbolType);
396     }
397   else
398     checkHook(metaHookList, symbolType);
399 }
400 
401 void
checkHook(DagNode * metaIdHook,SymbolType & symbolType)402 MetaLevel::checkHook(DagNode* metaIdHook, SymbolType& symbolType)
403 {
404   Symbol* mi = metaIdHook->symbol();
405   if (mi == idHookSymbol)
406     {
407       int id;
408       if (downQid(safeCast(FreeDagNode*, metaIdHook)->getArgument(0), id))
409 	{
410 	  int t = SymbolType::specialNameToBasicType(Token::name(id));
411 	  if (t != 0)
412 	    symbolType.setBasicType(t);
413 	}
414     }
415 }
416