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