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