1 /*
2
3 This file is part of the Maude 2 interpreter.
4
5 Copyright 1997-2014 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 // Routines for pretty printing a term into a vector of token codes.
25 //
26
27 void
bufferPrint(Vector<int> & buffer,Term * term,int printFlags)28 MixfixModule::bufferPrint(Vector<int>& buffer, Term* term, int printFlags)
29 {
30 globalIndent = 0; // HACK
31 prettyPrint(buffer, term, UNBOUNDED, UNBOUNDED, 0, UNBOUNDED, 0, false, printFlags);
32 }
33
34 void
prefix(Vector<int> & buffer,bool needDisambig)35 MixfixModule::prefix(Vector<int>& buffer, bool needDisambig)
36 {
37 if (needDisambig)
38 buffer.append(leftParen);
39 }
40
41 void
suffix(Vector<int> & buffer,Term * term,bool needDisambig,int printFlags)42 MixfixModule::suffix(Vector<int>& buffer, Term* term, bool needDisambig, int printFlags)
43 {
44 if (needDisambig)
45 {
46 Symbol* symbol = term->symbol();
47 int sortIndex = term->getSortIndex();
48 if (sortIndex <= Sort::KIND)
49 sortIndex = chooseDisambiguator(symbol);
50 buffer.append(rightParen);
51 //
52 // sortIndex will never be the index of a kind.
53 //
54 printDotSort(buffer, symbol->rangeComponent()->sort(sortIndex), printFlags);
55 }
56 }
57
58 void
handleVariable(Vector<int> & buffer,Term * term,int printFlags)59 MixfixModule::handleVariable(Vector<int>& buffer, Term* term, int printFlags)
60 {
61 VariableTerm* v = safeCast(VariableTerm*, term);
62 string fullName(Token::name(v->id()));
63 fullName += ':';
64 Sort* sort = v->getSort();
65 if (sort->index() == Sort::KIND)
66 {
67 buffer.append(Token::encode(fullName.c_str()));
68 printKind(buffer, sort, printFlags);
69 }
70 else
71 printVarSort(buffer, fullName, sort, printFlags);
72 }
73
74 bool
handleIter(Vector<int> & buffer,Term * term,SymbolInfo & si,bool rangeKnown,int printFlags)75 MixfixModule::handleIter(Vector<int>& buffer, Term* term, SymbolInfo& si, bool rangeKnown, int printFlags)
76 {
77 if (!(si.symbolType.hasFlag(SymbolType::ITER)))
78 return false;
79 if (si.symbolType.getBasicType() == SymbolType::SUCC_SYMBOL &&
80 (printFlags & Interpreter::PRINT_NUMBER))
81 {
82 SuccSymbol* succSymbol = safeCast(SuccSymbol*, term->symbol());
83 if (succSymbol->isNat(term))
84 {
85 const mpz_class& nat = succSymbol->getNat(term);
86 bool needDisambig = !rangeKnown && (kindsWithSucc.size() > 1 || overloadedIntegers.count(nat));
87 prefix(buffer, needDisambig);
88 char* name = mpz_get_str(0, 10, nat.get_mpz_t());
89 buffer.append(Token::encode(name));
90 free(name);
91 suffix(buffer, term, needDisambig, printFlags);
92 return true;
93 }
94 }
95 S_Term* st = safeCast(S_Term*, term);
96 const mpz_class& number = st->getNumber();
97 if (number == 1)
98 return false; // do default thing
99
100 // NEED TO FIX: disambig; i.e. we might have a regular operator called f^2
101 string prefixName;
102 makeIterName(prefixName, term->symbol()->id(), number);
103 printPrefixName(buffer, Token::encode(prefixName.c_str()), si, printFlags);
104 buffer.append(leftParen);
105 prettyPrint(buffer, st->getArgument(), PREFIX_GATHER, UNBOUNDED, 0, UNBOUNDED, 0, rangeKnown, printFlags);
106 buffer.append(rightParen);
107 return true;
108 }
109
110 bool
handleMinus(Vector<int> & buffer,Term * term,bool rangeKnown,int printFlags)111 MixfixModule::handleMinus(Vector<int>& buffer, Term* term, bool rangeKnown, int printFlags)
112 {
113 if (printFlags & Interpreter::PRINT_NUMBER)
114 {
115 const MinusSymbol* minusSymbol = safeCast(MinusSymbol*, term->symbol());
116 if (minusSymbol->isNeg(term))
117 {
118 mpz_class neg;
119 (void) minusSymbol->getNeg(term, neg);
120 bool needDisambig = !rangeKnown && (kindsWithMinus.size() > 1 || overloadedIntegers.count(neg));
121 prefix(buffer, needDisambig);
122
123 char* name = mpz_get_str(0, 10, neg.get_mpz_t());
124 buffer.append(Token::encode(name));
125 free(name);
126
127 suffix(buffer, term, needDisambig, printFlags);
128 return true;
129 }
130 }
131 return false;
132 }
133
134 bool
handleDivision(Vector<int> & buffer,Term * term,bool rangeKnown,int printFlags)135 MixfixModule::handleDivision(Vector<int>& buffer, Term* term, bool rangeKnown, int printFlags)
136 {
137 if (printFlags & Interpreter::PRINT_RAT)
138 {
139 const DivisionSymbol* divisionSymbol = safeCast(DivisionSymbol*, term->symbol());
140 if (divisionSymbol->isRat(term))
141 {
142 pair<mpz_class, mpz_class> rat;
143 rat.second = divisionSymbol->getRat(term, rat.first);
144 bool needDisambig = !rangeKnown && (kindsWithDivision.size() > 1 || overloadedRationals.count(rat));
145 prefix(buffer, needDisambig);
146
147 char* nn = mpz_get_str(0, 10, rat.first.get_mpz_t());
148 string prefixName(nn);
149 free(nn);
150 prefixName += '/';
151 char* dn = mpz_get_str(0, 10, rat.second.get_mpz_t());
152 prefixName += dn;
153 free(dn);
154 buffer.append(Token::encode(prefixName.c_str()));
155
156 suffix(buffer, term, needDisambig, printFlags);
157 return true;
158 }
159 }
160 return false;
161 }
162
163 void
handleFloat(Vector<int> & buffer,Term * term,bool rangeKnown,int printFlags)164 MixfixModule::handleFloat(Vector<int>& buffer, Term* term, bool rangeKnown, int printFlags)
165 {
166 double mfValue = safeCast(FloatTerm*, term)->getValue();
167 bool needDisambig = !rangeKnown && (floatSymbols.size() > 1 || overloadedFloats.count(mfValue));
168 prefix(buffer, needDisambig);
169 buffer.append(Token::doubleToCode(mfValue));
170 suffix(buffer, term, needDisambig, printFlags);
171 }
172
173 void
handleString(Vector<int> & buffer,Term * term,bool rangeKnown,int printFlags)174 MixfixModule::handleString(Vector<int>& buffer, Term* term, bool rangeKnown, int printFlags)
175 {
176 string strValue;
177 Token::ropeToString(safeCast(StringTerm*, term)->getValue(), strValue);
178 bool needDisambig = !rangeKnown && (stringSymbols.size() > 1 || overloadedStrings.count(strValue));
179 prefix(buffer, needDisambig);
180 buffer.append(Token::encode(strValue.c_str()));
181 suffix(buffer, term, needDisambig, printFlags);
182 }
183
184 void
handleQuotedIdentifier(Vector<int> & buffer,Term * term,bool rangeKnown,int printFlags)185 MixfixModule::handleQuotedIdentifier(Vector<int>& buffer, Term* term, bool rangeKnown, int printFlags)
186 {
187 int qidCode = safeCast(QuotedIdentifierTerm*, term)->getIdIndex();
188 bool needDisambig = !rangeKnown && (quotedIdentifierSymbols.size() > 1 || overloadedQuotedIdentifiers.count(qidCode));
189 prefix(buffer, needDisambig);
190 buffer.append(Token::quoteNameCode(qidCode));
191 suffix(buffer, term, needDisambig, printFlags);
192 }
193
194 void
handleSMT_NumberSymbol(Vector<int> & buffer,Term * term,bool rangeKnown,int printFlags)195 MixfixModule::handleSMT_NumberSymbol(Vector<int>& buffer, Term* term, bool rangeKnown, int printFlags)
196 {
197 //
198 // Get value.
199 //
200 SMT_NumberTerm* n = safeCast(SMT_NumberTerm*, term);
201 const mpq_class& value = n->getValue();
202 //
203 // Look up the index of our sort.
204 //
205 Symbol* symbol = term->symbol();
206 Sort* sort = symbol->getRangeSort();
207 //
208 // Determine whether we need disambiguation.
209 //
210 bool needDisambig;
211 SMT_Info::SMT_Type t = getSMT_Info().getType(sort);
212 Assert(t != SMT_Info::NOT_SMT, "bad SMT sort " << sort);
213 if (t == SMT_Info::INTEGER)
214 {
215 const mpz_class& integer = value.get_num();
216 needDisambig = !rangeKnown && (kindsWithSucc.size() > 1 || overloadedIntegers.count(integer));
217 }
218 else
219 {
220 Assert(t == SMT_Info::REAL, "SMT number sort expected");
221 pair<mpz_class, mpz_class> rat(value.get_num(), value.get_den());
222 needDisambig = !rangeKnown && (kindsWithDivision.size() > 1 || overloadedRationals.count(rat));
223 }
224
225 prefix(buffer, needDisambig);
226 buffer.append(getSMT_NumberToken(value, sort));
227 suffix(buffer, term, needDisambig, printFlags);
228 }
229
230 void
prettyPrint(Vector<int> & buffer,Term * term,int requiredPrec,int leftCapture,const ConnectedComponent * leftCaptureComponent,int rightCapture,const ConnectedComponent * rightCaptureComponent,bool rangeKnown,int printFlags)231 MixfixModule::prettyPrint(Vector<int>& buffer,
232 Term* term,
233 int requiredPrec,
234 int leftCapture,
235 const ConnectedComponent* leftCaptureComponent,
236 int rightCapture,
237 const ConnectedComponent* rightCaptureComponent,
238 bool rangeKnown,
239 int printFlags)
240 {
241 Symbol* symbol = term->symbol();
242 int index = symbol->getIndexWithinModule();
243 SymbolInfo& si = symbolInfo[index];
244 //
245 // Check for special i/o representation.
246 //
247 if (handleIter(buffer, term, si, rangeKnown, printFlags))
248 return;
249 int basicType = si.symbolType.getBasicType();
250 switch (basicType)
251 {
252 case SymbolType::MINUS_SYMBOL:
253 {
254 if (handleMinus(buffer, term, rangeKnown, printFlags))
255 return;
256 break;
257 }
258 case SymbolType::DIVISION_SYMBOL:
259 {
260 if (handleDivision(buffer, term, rangeKnown, printFlags))
261 return;
262 break;
263 }
264 case SymbolType::FLOAT:
265 {
266 handleFloat(buffer, term, rangeKnown, printFlags);
267 return;
268 }
269 case SymbolType::STRING:
270 {
271 handleString(buffer, term, rangeKnown, printFlags);
272 return;
273 }
274 case SymbolType::QUOTED_IDENTIFIER:
275 {
276 handleQuotedIdentifier(buffer, term, rangeKnown, printFlags);
277 return;
278 }
279 case SymbolType::VARIABLE:
280 {
281 handleVariable(buffer, term, printFlags);
282 return;
283 }
284 case SymbolType::SMT_NUMBER_SYMBOL:
285 {
286 handleSMT_NumberSymbol(buffer, term, rangeKnown, printFlags);
287 return;
288 }
289 default:
290 break;
291 }
292
293 int iflags = si.iflags;
294 bool needDisambig = !rangeKnown && ambiguous(iflags);
295 bool argRangeKnown = rangeOfArgumentsKnown(iflags, rangeKnown, needDisambig);
296 int nrArgs = symbol->arity();
297
298 prefix(buffer, needDisambig);
299 if (((printFlags & Interpreter::PRINT_MIXFIX) && si.mixfixSyntax.length() != 0) ||
300 (basicType == SymbolType::SORT_TEST))
301 {
302 //
303 // Mixfix case.
304 //
305 bool printWithParens = printFlags & Interpreter::PRINT_WITH_PARENS;
306 bool needParen = !needDisambig &&
307 (printWithParens || requiredPrec < si.prec ||
308 ((iflags & LEFT_BARE) && leftCapture <= si.gather[0] &&
309 leftCaptureComponent == symbol->domainComponent(0)) ||
310 ((iflags & RIGHT_BARE) && rightCapture <= si.gather[nrArgs - 1] &&
311 rightCaptureComponent == symbol->domainComponent(nrArgs - 1)));
312 bool needAssocParen = si.symbolType.hasFlag(SymbolType::ASSOC) &&
313 (printWithParens || si.gather[1] < si.prec ||
314 ((iflags & LEFT_BARE) && (iflags & RIGHT_BARE) &&
315 si.prec <= si.gather[0]));
316 if (needParen)
317 buffer.append(leftParen);
318 int nrTails = 1;
319 int pos = 0;
320 ArgumentIterator a(*term);
321 int moreArgs = a.valid();
322 for (int arg = 0; moreArgs; arg++)
323 {
324 Term* t = a.argument();
325 a.next();
326 moreArgs = a.valid();
327 pos = printTokens(buffer, si, pos, printFlags);
328 if (arg == nrArgs - 1 && moreArgs)
329 {
330 ++nrTails;
331 arg = 0;
332 if (needAssocParen)
333 buffer.append(leftParen);
334 pos = printTokens(buffer, si, 0, printFlags);
335 }
336 int lc = UNBOUNDED;
337 const ConnectedComponent* lcc = 0;
338 int rc = UNBOUNDED;
339 const ConnectedComponent* rcc = 0;
340 if (arg == 0 && (iflags & LEFT_BARE))
341 {
342 rc = si.prec;
343 rcc = symbol->domainComponent(0);
344 if (!needParen && !needDisambig)
345 {
346 lc = leftCapture;
347 lcc = leftCaptureComponent;
348 }
349 }
350 else if (!moreArgs && (iflags & RIGHT_BARE))
351 {
352 lc = si.prec;
353 lcc = symbol->domainComponent(nrArgs - 1);
354 if (!needParen && !needDisambig)
355 {
356 rc = rightCapture;
357 rcc = rightCaptureComponent;
358 }
359 }
360 prettyPrint(buffer, t, si.gather[arg], lc, lcc, rc, rcc, argRangeKnown, printFlags);
361 }
362 printTails(buffer, si, pos, nrTails, needAssocParen, printFlags);
363 if (needParen)
364 buffer.append(rightParen);
365 }
366 else
367 {
368 //
369 // Prefix case.
370 //
371 int id = symbol->id();
372 printPrefixName(buffer, id, si, printFlags);
373 ArgumentIterator a(*term);
374 if (a.valid())
375 {
376 int nrTails = 1;
377 buffer.append(leftParen);
378 for (int arg = 0;; arg++)
379 {
380 Term* t = a.argument();
381 a.next();
382 int moreArgs = a.valid();
383 if (arg >= nrArgs - 1 &&
384 !(printFlags & Interpreter::PRINT_FLAT) &&
385 moreArgs)
386 {
387 ++nrTails;
388 printPrefixName(buffer, id, si, printFlags);
389 buffer.append(leftParen);
390 }
391 prettyPrint(buffer, t, PREFIX_GATHER, UNBOUNDED, 0, UNBOUNDED, 0, argRangeKnown, printFlags);
392 if (!moreArgs)
393 break;
394 buffer.append(comma);
395 }
396 while (nrTails-- > 0)
397 buffer.append(rightParen);
398 }
399 }
400 suffix(buffer, term, needDisambig, printFlags);
401 }
402
403 void
printKind(Vector<int> & buffer,const Sort * kind,int printFlags)404 MixfixModule::printKind(Vector<int>& buffer, const Sort* kind, int printFlags)
405 {
406 Assert(kind != 0, "null kind");
407 ConnectedComponent* c = kind->component();
408 Assert(c != 0, "null conponent");
409
410 buffer.append(leftBracket);
411 printSort(buffer, c->sort(1), printFlags);
412 int nrMax = c->nrMaximalSorts();
413 for (int i = 2; i <= nrMax; i++)
414 {
415 buffer.append(comma);
416 printSort(buffer, c->sort(i), printFlags);
417 }
418 buffer.append(rightBracket);
419 }
420
421 void
printSort(Vector<int> & buffer,const Sort * sort,int printFlags)422 MixfixModule::printSort(Vector<int>& buffer, const Sort* sort, int printFlags)
423 {
424 int name = sort->id();
425 if (Token::auxProperty(name) == Token::AUX_STRUCTURED_SORT &&
426 interpreter.getPrintFlag(Interpreter::PRINT_MIXFIX))
427 {
428 Vector<int> parts;
429 Token::splitParameterizedSort(name, parts);
430 FOR_EACH_CONST(i, Vector<int>, parts)
431 buffer.append(*i);
432 }
433 else
434 buffer.append(name);
435 }
436
437 void
printDotSort(Vector<int> & buffer,const Sort * sort,int printFlags)438 MixfixModule::printDotSort(Vector<int>& buffer, const Sort* sort, int printFlags)
439 {
440 int name = sort->id();
441 if (Token::auxProperty(name) == Token::AUX_STRUCTURED_SORT &&
442 interpreter.getPrintFlag(Interpreter::PRINT_MIXFIX))
443 {
444 Vector<int> parts;
445 Token::splitParameterizedSort(name, parts);
446 parts[0] = Token::dotNameCode(parts[0]);
447 FOR_EACH_CONST(i, Vector<int>, parts)
448 buffer.append(*i);
449 }
450 else
451 buffer.append(Token::dotNameCode(name));
452 }
453
454 void
printVarSort(Vector<int> & buffer,string & fullName,const Sort * sort,int printFlags)455 MixfixModule::printVarSort(Vector<int>& buffer, string& fullName, const Sort* sort, int printFlags)
456 {
457 int name = sort->id();
458 if (Token::auxProperty(name) == Token::AUX_STRUCTURED_SORT &&
459 interpreter.getPrintFlag(Interpreter::PRINT_MIXFIX))
460 {
461 Vector<int> parts;
462 Token::splitParameterizedSort(name, parts);
463 fullName += Token::name(parts[0]);
464 parts[0] = Token::encode(fullName.c_str());
465 FOR_EACH_CONST(i, Vector<int>, parts)
466 buffer.append(*i);
467 }
468 else
469 {
470 fullName += Token::name(name);
471 buffer.append(Token::encode(fullName.c_str()));
472 }
473 }
474
475 int
printTokens(Vector<int> & buffer,const SymbolInfo & si,int pos,int printFlags)476 MixfixModule::printTokens(Vector<int>& buffer, const SymbolInfo& si, int pos, int printFlags)
477 {
478 bool hasFormat = (printFlags & Interpreter::PRINT_FORMAT) && (si.format.length() > 0);
479 for (;;)
480 {
481 int token = si.mixfixSyntax[pos++];
482 if (token == underscore)
483 break;
484 if (hasFormat)
485 handleFormat(buffer, si.format[pos - 1]);
486 buffer.append(token);
487 }
488 if (hasFormat)
489 handleFormat(buffer, si.format[pos - 1]);
490 return pos;
491 }
492
493 void
printTails(Vector<int> & buffer,const SymbolInfo & si,int pos,int nrTails,bool needAssocParen,int printFlags)494 MixfixModule::printTails(Vector<int>& buffer,
495 const SymbolInfo& si,
496 int pos,
497 int nrTails,
498 bool needAssocParen,
499 int printFlags)
500 {
501 bool hasFormat = (printFlags & Interpreter::PRINT_FORMAT) && (si.format.length() > 0);
502 int mixfixLength = si.mixfixSyntax.length();
503 for (int i = 0;;)
504 {
505 for (int j = pos; j < mixfixLength; j++)
506 {
507 if (hasFormat)
508 handleFormat(buffer, si.format[j]);
509 buffer.append(si.mixfixSyntax[j]);
510 }
511 if (hasFormat)
512 handleFormat(buffer, si.format[mixfixLength]);
513 if (++i == nrTails)
514 break;
515 if (needAssocParen)
516 buffer.append(rightParen);
517 }
518 }
519
520 void
printPrefixName(Vector<int> & buffer,int prefixName,SymbolInfo & si,int printFlags)521 MixfixModule::printPrefixName(Vector<int>& buffer, int prefixName, SymbolInfo& si, int printFlags)
522 {
523 if ((printFlags & Interpreter::PRINT_FORMAT) && (si.format.length() == 2))
524 {
525 handleFormat(buffer, si.format[0]);
526 buffer.append(prefixName);
527 handleFormat(buffer, si.format[1]);
528 }
529 else
530 buffer.append(prefixName);
531 }
532
533 void
handleFormat(Vector<int> & buffer,int spaceToken)534 MixfixModule::handleFormat(Vector<int>& buffer, int spaceToken)
535 {
536 for (const char* cmd = Token::name(spaceToken); *cmd; cmd++)
537 {
538 switch (*cmd)
539 {
540 case '+':
541 {
542 ++globalIndent;
543 break;
544 }
545 case '-':
546 {
547 if (globalIndent > 0)
548 --globalIndent;
549 break;
550 }
551 case 'i':
552 {
553 if (globalIndent > 0)
554 {
555 int t = Token::encode("\\s");
556 for (int i = 0; i < globalIndent; i++)
557 buffer.append(t);
558 }
559 break;
560 }
561 #define MACRO(m, t) case m:
562 #include "ansiEscapeSequences.cc"
563 #undef MACRO
564 case 'o':
565 case 'n':
566 case 't':
567 case 's':
568 {
569 static char strg[3] = "\\!"; // HACK
570 strg[1] = *cmd;
571 buffer.append(Token::encode(strg));
572 break;
573 }
574 }
575 }
576 }
577