this repo has no description
at develop 56 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3/* 4 * Main authors: 5 * Pierre Wilke <wilke.pierre@gmail.com> 6 * Guido Tack <guido.tack@monash.edu> 7 */ 8 9/* This Source Code Form is subject to the terms of the Mozilla Public 10 * License, v. 2.0. If a copy of the MPL was not distributed with this 11 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 12 13#include <minizinc/astexception.hh> 14#include <minizinc/hash.hh> 15#include <minizinc/iter.hh> 16#include <minizinc/model.hh> 17#include <minizinc/prettyprinter.hh> 18 19#include <iomanip> 20#include <limits> 21#include <map> 22#include <sstream> 23#include <string> 24#include <vector> 25 26namespace MiniZinc { 27 28int precedence(const Expression* e) { 29 if (const BinOp* bo = e->dyn_cast<BinOp>()) { 30 switch (bo->op()) { 31 case BOT_EQUIV: 32 return 1200; 33 case BOT_IMPL: 34 return 1100; 35 case BOT_RIMPL: 36 return 1100; 37 case BOT_OR: 38 return 1000; 39 case BOT_XOR: 40 return 1000; 41 case BOT_AND: 42 return 900; 43 case BOT_LE: 44 return 800; 45 case BOT_LQ: 46 return 800; 47 case BOT_GR: 48 return 800; 49 case BOT_GQ: 50 return 800; 51 case BOT_EQ: 52 return 800; 53 case BOT_NQ: 54 return 800; 55 case BOT_IN: 56 return 700; 57 case BOT_SUBSET: 58 return 700; 59 case BOT_SUPERSET: 60 return 700; 61 case BOT_UNION: 62 return 600; 63 case BOT_DIFF: 64 return 600; 65 case BOT_SYMDIFF: 66 return 600; 67 case BOT_DOTDOT: 68 return 500; 69 case BOT_PLUS: 70 return 400; 71 case BOT_MINUS: 72 return 400; 73 case BOT_MULT: 74 return 300; 75 case BOT_IDIV: 76 return 300; 77 case BOT_MOD: 78 return 300; 79 case BOT_DIV: 80 return 300; 81 case BOT_INTERSECT: 82 return 300; 83 case BOT_POW: 84 return 200; 85 case BOT_PLUSPLUS: 86 return 200; 87 default: 88 assert(false); 89 return -1; 90 } 91 92 } else if (e->isa<Let>()) { 93 return 1300; 94 95 } else { 96 return 0; 97 } 98} 99 100enum Assoc { AS_LEFT, AS_RIGHT, AS_NONE }; 101 102Assoc assoc(const BinOp* bo) { 103 switch (bo->op()) { 104 case BOT_LE: 105 case BOT_LQ: 106 case BOT_GR: 107 case BOT_GQ: 108 case BOT_NQ: 109 case BOT_EQ: 110 case BOT_IN: 111 case BOT_SUBSET: 112 case BOT_SUPERSET: 113 case BOT_DOTDOT: 114 return AS_NONE; 115 case BOT_PLUSPLUS: 116 return AS_RIGHT; 117 default: 118 return AS_LEFT; 119 } 120} 121 122enum Parentheses { PN_LEFT = 1, PN_RIGHT = 2 }; 123 124Parentheses needParens(const BinOp* bo, const Expression* left, const Expression* right) { 125 int pbo = precedence(bo); 126 int pl = precedence(left); 127 int pr = precedence(right); 128 int ret = (pbo < pl) || (pbo == pl && assoc(bo) != AS_LEFT); 129 ret += 2 * ((pbo < pr) || (pbo == pr && assoc(bo) != AS_RIGHT)); 130 return static_cast<Parentheses>(ret); 131} 132 133std::string Printer::escapeStringLit(const ASTString& s) { 134 const char* sc = s.c_str(); 135 std::ostringstream ret; 136 for (unsigned int i = 0; i < s.size(); i++) { 137 switch (sc[i]) { 138 case '\n': 139 ret << "\\n"; 140 break; 141 case '\t': 142 ret << "\\t"; 143 break; 144 case '"': 145 ret << "\\\""; 146 break; 147 case '\\': 148 ret << "\\\\"; 149 break; 150 default: 151 ret << sc[i]; 152 } 153 } 154 return ret.str(); 155} 156 157void ppFloatVal(std::ostream& os, const FloatVal& fv, bool hexFloat) { 158 std::ostringstream oss; 159 if (fv.isFinite()) { 160 if (hexFloat) { 161 throw InternalError("disabled due to hexfloat being not supported by g++ 4.9"); 162 // std::hexfloat(oss); 163 oss << fv.toDouble(); 164 os << oss.str(); 165 } else { 166 oss << std::setprecision(std::numeric_limits<double>::digits10 + 1); 167 oss << fv; 168 if (oss.str().find("e") == std::string::npos && oss.str().find(".") == std::string::npos) 169 oss << ".0"; 170 os << oss.str(); 171 } 172 } else { 173 if (fv.isPlusInfinity()) 174 os << "infinity"; 175 else 176 os << "-infinity"; 177 } 178} 179 180class PlainPrinter { 181public: 182 EnvI* env; 183 std::ostream& os; 184 bool _flatZinc; 185 PlainPrinter(std::ostream& os0, bool flatZinc, EnvI* env0) 186 : env(env0), os(os0), _flatZinc(flatZinc) {} 187 188 void p(const Type& type, const Expression* e) { 189 switch (type.ti()) { 190 case Type::TI_PAR: 191 break; 192 case Type::TI_VAR: 193 os << "var "; 194 break; 195 } 196 if (type.ot() == Type::OT_OPTIONAL) os << "opt "; 197 if (type.st() == Type::ST_SET) os << "set of "; 198 if (e == NULL) { 199 switch (type.bt()) { 200 case Type::BT_INT: 201 os << "int"; 202 break; 203 case Type::BT_BOOL: 204 os << "bool"; 205 break; 206 case Type::BT_FLOAT: 207 os << "float"; 208 break; 209 case Type::BT_STRING: 210 os << "string"; 211 break; 212 case Type::BT_ANN: 213 os << "ann"; 214 break; 215 case Type::BT_BOT: 216 os << "bot"; 217 break; 218 case Type::BT_TOP: 219 os << "top"; 220 break; 221 case Type::BT_UNKNOWN: 222 os << "???"; 223 break; 224 } 225 } else { 226 p(e); 227 } 228 } 229 230 void p(const Annotation& ann) { 231 for (ExpressionSetIter it = ann.begin(); it != ann.end(); ++it) { 232 os << ":: "; 233 p(*it); 234 } 235 } 236 237 void p(const Expression* e) { 238 if (e == NULL) return; 239 switch (e->eid()) { 240 case Expression::E_INTLIT: 241 os << e->cast<IntLit>()->v(); 242 break; 243 case Expression::E_FLOATLIT: { 244 ppFloatVal(os, e->cast<FloatLit>()->v()); 245 } break; 246 case Expression::E_SETLIT: { 247 const SetLit& sl = *e->cast<SetLit>(); 248 if (sl.isv()) { 249 if (sl.isv()->size() == 0) { 250 os << (_flatZinc ? "1..0" : "{}"); 251 } else if (sl.isv()->size() == 1) { 252 os << sl.isv()->min(0) << ".." << sl.isv()->max(0); 253 } else { 254 if (!sl.isv()->min(0).isFinite()) 255 os << sl.isv()->min(0) << ".." << sl.isv()->max(0) << "++"; 256 os << "{"; 257 for (IntSetRanges isr(sl.isv()); isr();) { 258 if (isr.min().isFinite() && isr.max().isFinite()) { 259 for (IntVal i = isr.min(); i <= isr.max(); i++) { 260 os << i; 261 if (i < isr.max()) os << ","; 262 } 263 ++isr; 264 if (isr()) os << ","; 265 } 266 } 267 os << "}"; 268 if (!sl.isv()->max(sl.isv()->size() - 1).isFinite()) 269 os << "++" << sl.isv()->min(sl.isv()->size() - 1) << ".." 270 << sl.isv()->max(sl.isv()->size() - 1); 271 } 272 } else if (sl.fsv()) { 273 if (sl.fsv()->size() == 0) { 274 os << (_flatZinc ? "1.0..0.0" : "{}"); 275 } else if (sl.fsv()->size() == 1) { 276 ppFloatVal(os, sl.fsv()->min(0)); 277 os << ".."; 278 ppFloatVal(os, sl.fsv()->max(0)); 279 } else { 280 bool allSingleton = true; 281 for (FloatSetRanges isr(sl.fsv()); isr(); ++isr) { 282 if (isr.min() != isr.max()) { 283 allSingleton = false; 284 break; 285 } 286 } 287 if (allSingleton) { 288 os << "{"; 289 bool first = true; 290 for (FloatSetRanges isr(sl.fsv()); isr(); ++isr) { 291 if (!first) os << ","; 292 first = false; 293 ppFloatVal(os, isr.min()); 294 } 295 os << "}"; 296 } else { 297 bool first = true; 298 for (FloatSetRanges isr(sl.fsv()); isr(); ++isr) { 299 if (!first) os << "++"; 300 first = false; 301 ppFloatVal(os, isr.min()); 302 os << ".."; 303 ppFloatVal(os, isr.max()); 304 } 305 } 306 } 307 } else { 308 os << "{"; 309 for (unsigned int i = 0; i < sl.v().size(); i++) { 310 p(sl.v()[i]); 311 if (i < sl.v().size() - 1) os << ","; 312 } 313 os << "}"; 314 } 315 } break; 316 case Expression::E_BOOLLIT: 317 os << (e->cast<BoolLit>()->v() ? "true" : "false"); 318 break; 319 case Expression::E_STRINGLIT: 320 os << "\"" << Printer::escapeStringLit(e->cast<StringLit>()->v()) << "\""; 321 break; 322 case Expression::E_ID: { 323 if (e == constants().absent) { 324 os << "<>"; 325 } else { 326 const Id* id = e->cast<Id>(); 327 if (id->decl()) id = id->decl()->id(); 328 if (id->idn() == -1) { 329 os << id->v(); 330 } else { 331 os << "X_INTRODUCED_" << id->idn() << "_"; 332 } 333 } 334 } break; 335 case Expression::E_TIID: 336 os << "$" << e->cast<TIId>()->v(); 337 break; 338 case Expression::E_ANON: 339 os << "_"; 340 break; 341 case Expression::E_ARRAYLIT: { 342 const ArrayLit& al = *e->cast<ArrayLit>(); 343 int n = al.dims(); 344 if (n == 1 && al.min(0) == 1) { 345 os << "["; 346 for (unsigned int i = 0; i < al.size(); i++) { 347 p(al[i]); 348 if (i < al.size() - 1) os << ","; 349 } 350 os << "]"; 351 } else if (n == 2 && al.min(0) == 1 && al.min(1) == 1 && al.max(1) != 0) { 352 os << "[|"; 353 for (int i = 0; i < al.max(0); i++) { 354 for (int j = 0; j < al.max(1); j++) { 355 p(al[i * al.max(1) + j]); 356 if (j < al.max(1) - 1) os << ","; 357 } 358 if (i < al.max(0) - 1) os << "|"; 359 } 360 os << "|]"; 361 } else { 362 os << "array" << n << "d("; 363 for (int i = 0; i < al.dims(); i++) { 364 os << al.min(i) << ".." << al.max(i); 365 os << ","; 366 } 367 os << "["; 368 for (unsigned int i = 0; i < al.size(); i++) { 369 p(al[i]); 370 if (i < al.size() - 1) os << ","; 371 } 372 os << "])"; 373 } 374 } break; 375 case Expression::E_ARRAYACCESS: { 376 const ArrayAccess& aa = *e->cast<ArrayAccess>(); 377 p(aa.v()); 378 os << "["; 379 for (unsigned int i = 0; i < aa.idx().size(); i++) { 380 p(aa.idx()[i]); 381 if (i < aa.idx().size() - 1) os << ","; 382 } 383 os << "]"; 384 } break; 385 case Expression::E_COMP: { 386 const Comprehension& c = *e->cast<Comprehension>(); 387 os << (c.set() ? "{" : "["); 388 p(c.e()); 389 os << " | "; 390 for (int i = 0; i < c.n_generators(); i++) { 391 for (int j = 0; j < c.n_decls(i); j++) { 392 os << c.decl(i, j)->id()->v(); 393 if (j < c.n_decls(i) - 1) os << ","; 394 } 395 if (c.in(i) == NULL) { 396 os << " = "; 397 p(c.where(i)); 398 } else { 399 os << " in "; 400 p(c.in(i)); 401 if (c.where(i) != NULL) { 402 os << " where "; 403 p(c.where(i)); 404 } 405 } 406 if (i < c.n_generators()) os << ", "; 407 } 408 os << (c.set() ? "}" : "]"); 409 } break; 410 case Expression::E_ITE: { 411 const ITE& ite = *e->cast<ITE>(); 412 for (int i = 0; i < ite.size(); i++) { 413 os << (i == 0 ? "if " : " elseif "); 414 p(ite.e_if(i)); 415 os << " then "; 416 p(ite.e_then(i)); 417 } 418 os << " else "; 419 p(ite.e_else()); 420 os << " endif"; 421 } break; 422 case Expression::E_BINOP: { 423 const BinOp& bo = *e->cast<BinOp>(); 424 Parentheses ps = needParens(&bo, bo.lhs(), bo.rhs()); 425 if (ps & PN_LEFT) os << "("; 426 p(bo.lhs()); 427 if (ps & PN_LEFT) os << ")"; 428 switch (bo.op()) { 429 case BOT_PLUS: 430 os << "+"; 431 break; 432 case BOT_MINUS: 433 os << "-"; 434 break; 435 case BOT_MULT: 436 os << "*"; 437 break; 438 case BOT_POW: 439 os << "^"; 440 break; 441 case BOT_DIV: 442 os << "/"; 443 break; 444 case BOT_IDIV: 445 os << " div "; 446 break; 447 case BOT_MOD: 448 os << " mod "; 449 break; 450 case BOT_LE: 451 os << " < "; 452 break; 453 case BOT_LQ: 454 os << "<="; 455 break; 456 case BOT_GR: 457 os << " > "; 458 break; 459 case BOT_GQ: 460 os << ">="; 461 break; 462 case BOT_EQ: 463 os << "=="; 464 break; 465 case BOT_NQ: 466 os << "!="; 467 break; 468 case BOT_IN: 469 os << " in "; 470 break; 471 case BOT_SUBSET: 472 os << " subset "; 473 break; 474 case BOT_SUPERSET: 475 os << " superset "; 476 break; 477 case BOT_UNION: 478 os << " union "; 479 break; 480 case BOT_DIFF: 481 os << " diff "; 482 break; 483 case BOT_SYMDIFF: 484 os << " symdiff "; 485 break; 486 case BOT_INTERSECT: 487 os << " intersect "; 488 break; 489 case BOT_PLUSPLUS: 490 os << "++"; 491 break; 492 case BOT_EQUIV: 493 os << " <-> "; 494 break; 495 case BOT_IMPL: 496 os << " -> "; 497 break; 498 case BOT_RIMPL: 499 os << " <- "; 500 break; 501 case BOT_OR: 502 os << " \\/ "; 503 break; 504 case BOT_AND: 505 os << " /\\ "; 506 break; 507 case BOT_XOR: 508 os << " xor "; 509 break; 510 case BOT_DOTDOT: 511 os << ".."; 512 break; 513 default: 514 assert(false); 515 break; 516 } 517 518 if (ps & PN_RIGHT) os << "("; 519 p(bo.rhs()); 520 if (ps & PN_RIGHT) os << ")"; 521 } break; 522 case Expression::E_UNOP: { 523 const UnOp& uo = *e->cast<UnOp>(); 524 switch (uo.op()) { 525 case UOT_NOT: 526 os << "not "; 527 break; 528 case UOT_PLUS: 529 os << "+"; 530 break; 531 case UOT_MINUS: 532 os << "-"; 533 break; 534 default: 535 assert(false); 536 break; 537 } 538 bool needParen = (uo.e()->isa<BinOp>() || uo.e()->isa<UnOp>() || !uo.ann().isEmpty()); 539 if (needParen) os << "("; 540 p(uo.e()); 541 if (needParen) os << ")"; 542 } break; 543 case Expression::E_CALL: { 544 const Call& c = *e->cast<Call>(); 545 os << c.id() << "("; 546 for (unsigned int i = 0; i < c.n_args(); i++) { 547 p(c.arg(i)); 548 if (i < c.n_args() - 1) os << ","; 549 } 550 os << ")"; 551 } break; 552 case Expression::E_VARDECL: { 553 const VarDecl& vd = *e->cast<VarDecl>(); 554 p(vd.ti()); 555 if (!vd.ti()->isEnum()) { 556 os << ":"; 557 } 558 if (vd.id()->idn() != -1) { 559 os << " X_INTRODUCED_" << vd.id()->idn() << "_"; 560 } else if (vd.id()->v().size() != 0) 561 os << " " << vd.id()->v(); 562 if (vd.introduced()) { 563 os << " ::var_is_introduced "; 564 } 565 p(vd.ann()); 566 if (vd.e()) { 567 os << " = "; 568 p(vd.e()); 569 } 570 } break; 571 case Expression::E_LET: { 572 const Let& l = *e->cast<Let>(); 573 os << "let {"; 574 575 for (unsigned int i = 0; i < l.let().size(); i++) { 576 const Expression* li = l.let()[i]; 577 if (!li->isa<VarDecl>()) os << "constraint "; 578 p(li); 579 if (i < l.let().size() - 1) os << ", "; 580 } 581 os << "} in ("; 582 p(l.in()); 583 os << ")"; 584 } break; 585 case Expression::E_TI: { 586 const TypeInst& ti = *e->cast<TypeInst>(); 587 if (ti.isEnum()) { 588 os << "enum"; 589 } else if (env) { 590 os << ti.type().toString(*env); 591 } else { 592 if (ti.isarray()) { 593 os << "array ["; 594 for (unsigned int i = 0; i < ti.ranges().size(); i++) { 595 p(Type::parint(), ti.ranges()[i]); 596 if (i < ti.ranges().size() - 1) os << ","; 597 } 598 os << "] of "; 599 } 600 p(ti.type(), ti.domain()); 601 } 602 } 603 } 604 if (!e->isa<VarDecl>()) { 605 p(e->ann()); 606 } 607 } 608 609 void p(const Item* i) { 610 if (i == NULL) return; 611 if (i->removed()) os << "% "; 612 switch (i->iid()) { 613 case Item::II_INC: 614 os << "include \"" << i->cast<IncludeI>()->f() << "\""; 615 break; 616 case Item::II_VD: 617 p(i->cast<VarDeclI>()->e()); 618 break; 619 case Item::II_ASN: 620 os << i->cast<AssignI>()->id() << " = "; 621 p(i->cast<AssignI>()->e()); 622 break; 623 case Item::II_CON: 624 os << "constraint "; 625 p(i->cast<ConstraintI>()->e()); 626 break; 627 case Item::II_SOL: { 628 const SolveI* si = i->cast<SolveI>(); 629 os << "solve "; 630 p(si->ann()); 631 switch (si->st()) { 632 case SolveI::ST_SAT: 633 os << " satisfy"; 634 break; 635 case SolveI::ST_MIN: 636 os << " minimize "; 637 p(si->e()); 638 break; 639 case SolveI::ST_MAX: 640 os << " maximize "; 641 p(si->e()); 642 break; 643 } 644 } break; 645 case Item::II_OUT: 646 os << "output "; 647 p(i->cast<OutputI>()->e()); 648 break; 649 case Item::II_FUN: { 650 const FunctionI& fi = *i->cast<FunctionI>(); 651 if (fi.ti()->type().isann() && fi.e() == NULL) { 652 os << "annotation "; 653 } else if (fi.ti()->type() == Type::parbool()) { 654 os << "test "; 655 } else if (fi.ti()->type() == Type::varbool()) { 656 os << "predicate "; 657 } else { 658 os << "function "; 659 p(fi.ti()); 660 os << " : "; 661 } 662 os << fi.id(); 663 if (fi.params().size() > 0) { 664 os << "("; 665 for (unsigned int i = 0; i < fi.params().size(); i++) { 666 p(fi.params()[i]); 667 if (i < fi.params().size() - 1) os << ","; 668 } 669 os << ")"; 670 } 671 p(fi.ann()); 672 if (fi.e()) { 673 os << " = "; 674 p(fi.e()); 675 } 676 } break; 677 } 678 os << ";" << std::endl; 679 } 680}; 681 682template <class T> 683class ExpressionMapper { 684protected: 685 T& _t; 686 687public: 688 ExpressionMapper(T& t) : _t(t) {} 689 typename T::ret map(const Expression* e) { 690 switch (e->eid()) { 691 case Expression::E_INTLIT: 692 return _t.mapIntLit(*e->cast<IntLit>()); 693 case Expression::E_FLOATLIT: 694 return _t.mapFloatLit(*e->cast<FloatLit>()); 695 case Expression::E_SETLIT: 696 return _t.mapSetLit(*e->cast<SetLit>()); 697 case Expression::E_BOOLLIT: 698 return _t.mapBoolLit(*e->cast<BoolLit>()); 699 case Expression::E_STRINGLIT: 700 return _t.mapStringLit(*e->cast<StringLit>()); 701 case Expression::E_ID: 702 return _t.mapId(*e->cast<Id>()); 703 case Expression::E_ANON: 704 return _t.mapAnonVar(*e->cast<AnonVar>()); 705 case Expression::E_ARRAYLIT: 706 return _t.mapArrayLit(*e->cast<ArrayLit>()); 707 case Expression::E_ARRAYACCESS: 708 return _t.mapArrayAccess(*e->cast<ArrayAccess>()); 709 case Expression::E_COMP: 710 return _t.mapComprehension(*e->cast<Comprehension>()); 711 case Expression::E_ITE: 712 return _t.mapITE(*e->cast<ITE>()); 713 case Expression::E_BINOP: 714 return _t.mapBinOp(*e->cast<BinOp>()); 715 case Expression::E_UNOP: 716 return _t.mapUnOp(*e->cast<UnOp>()); 717 case Expression::E_CALL: 718 return _t.mapCall(*e->cast<Call>()); 719 case Expression::E_VARDECL: 720 return _t.mapVarDecl(*e->cast<VarDecl>()); 721 case Expression::E_LET: 722 return _t.mapLet(*e->cast<Let>()); 723 case Expression::E_TI: 724 return _t.mapTypeInst(*e->cast<TypeInst>()); 725 case Expression::E_TIID: 726 return _t.mapTIId(*e->cast<TIId>()); 727 default: 728 assert(false); 729 return typename T::ret(); 730 break; 731 } 732 } 733}; 734 735class Document { 736private: 737 int level; 738 739public: 740 Document() : level(0) {} 741 virtual ~Document() {} 742 int getLevel() { return level; } 743 // Make this object a child of "d". 744 virtual void setParent(Document* d) { level = d->level + 1; } 745}; 746 747class BreakPoint : public Document { 748private: 749 bool dontSimplify; 750 751public: 752 BreakPoint() { dontSimplify = false; } 753 BreakPoint(bool ds) { dontSimplify = ds; } 754 virtual ~BreakPoint() {} 755 void setDontSimplify(bool b) { dontSimplify = b; } 756 bool getDontSimplify() { return dontSimplify; } 757}; 758 759class StringDocument : public Document { 760private: 761 std::string stringDocument; 762 763public: 764 StringDocument() {} 765 virtual ~StringDocument() {} 766 767 StringDocument(std::string s) : stringDocument(s) {} 768 769 std::string getString() { return stringDocument; } 770 void setString(std::string s) { stringDocument = s; } 771}; 772 773class DocumentList : public Document { 774private: 775 std::vector<Document*> docs; 776 std::string beginToken; 777 std::string separator; 778 std::string endToken; 779 bool unbreakable; 780 bool alignment; 781 782public: 783 virtual ~DocumentList() { 784 std::vector<Document*>::iterator it; 785 for (it = docs.begin(); it != docs.end(); it++) { 786 delete *it; 787 } 788 } 789 DocumentList(std::string _beginToken = "", std::string _separator = "", 790 std::string _endToken = "", bool _alignment = true); 791 792 void addDocumentToList(Document* d) { 793 docs.push_back(d); 794 d->setParent(this); 795 } 796 797 void setParent(Document* d) { 798 Document::setParent(d); 799 std::vector<Document*>::iterator it; 800 for (it = docs.begin(); it != docs.end(); it++) { 801 (*it)->setParent(this); 802 } 803 } 804 805 void addStringToList(std::string s) { addDocumentToList(new StringDocument(s)); } 806 807 void addBreakPoint(bool b = false) { addDocumentToList(new BreakPoint(b)); } 808 809 std::vector<Document*> getDocs() { return docs; } 810 811 void setList(std::vector<Document*> ld) { docs = ld; } 812 813 std::string getBeginToken() { return beginToken; } 814 815 std::string getEndToken() { return endToken; } 816 817 std::string getSeparator() { return separator; } 818 819 bool getUnbreakable() { return unbreakable; } 820 821 void setUnbreakable(bool b) { unbreakable = b; } 822 823 bool getAlignment() { return alignment; } 824}; 825 826DocumentList::DocumentList(std::string _beginToken, std::string _separator, std::string _endToken, 827 bool _alignment) { 828 beginToken = _beginToken; 829 separator = _separator; 830 endToken = _endToken; 831 alignment = _alignment; 832 unbreakable = false; 833} 834 835class Line { 836private: 837 int indentation; 838 int lineLength; 839 std::vector<std::string> text; 840 841public: 842 Line() : indentation(0), lineLength(0), text(0) {} 843 Line(const Line& l) : indentation(l.indentation), lineLength(l.lineLength), text(l.text) {} 844 Line(const int indent) : indentation(indent), lineLength(0), text(0) {} 845 bool operator==(const Line& l) { return &l == this; } 846 847 void setIndentation(int i) { indentation = i; } 848 849 int getLength() const { return lineLength; } 850 int getIndentation() const { return indentation; } 851 int getSpaceLeft(int maxwidth); 852 void addString(const std::string& s); 853 void concatenateLines(Line& l); 854 855 void print(std::ostream& os) const { 856 for (int i = 0; i < getIndentation(); i++) { 857 os << " "; 858 } 859 std::vector<std::string>::const_iterator it; 860 for (it = text.begin(); it != text.end(); it++) { 861 os << (*it); 862 } 863 os << "\n"; 864 } 865}; 866 867int Line::getSpaceLeft(int maxwidth) { return maxwidth - lineLength - indentation; } 868void Line::addString(const std::string& s) { 869 lineLength += static_cast<int>(s.size()); 870 text.push_back(s); 871} 872void Line::concatenateLines(Line& l) { 873 text.insert(text.end(), l.text.begin(), l.text.end()); 874 lineLength += l.lineLength; 875} 876 877class LinesToSimplify { 878private: 879 std::map<int, std::vector<int> > lines; 880 881 // (i,j) in parent <=> j can only be simplified if i is simplified 882 std::vector<std::pair<int, int> > parent; 883 /* 884 * if i can't simplify, remove j and his parents 885 */ 886 // mostRecentlyAdded[level] = line of the most recently added 887 std::map<int, int> mostRecentlyAdded; 888 889public: 890 std::vector<int>* getLinesForPriority(int p) { 891 std::map<int, std::vector<int> >::iterator it; 892 for (it = lines.begin(); it != lines.end(); it++) { 893 if (it->first == p) return &(it->second); 894 } 895 return NULL; 896 } 897 void addLine(int p, int l, int par = -1) { 898 if (par == -1) { 899 for (int i = p - 1; i >= 0; i--) { 900 std::map<int, int>::iterator it = mostRecentlyAdded.find(i); 901 if (it != mostRecentlyAdded.end()) { 902 par = it->second; 903 break; 904 } 905 } 906 } 907 if (par != -1) parent.push_back(std::pair<int, int>(l, par)); 908 mostRecentlyAdded.insert(std::pair<int, int>(p, l)); 909 std::map<int, std::vector<int> >::iterator it; 910 for (it = lines.begin(); it != lines.end(); it++) { 911 if (it->first == p) { 912 it->second.push_back(l); 913 return; 914 } 915 } 916 std::vector<int> v; 917 v.push_back(l); 918 lines.insert(std::pair<int, std::vector<int> >(p, v)); 919 } 920 void decrementLine(std::vector<int>* vec, int l) { 921 std::vector<int>::iterator vit; 922 if (vec != NULL) { 923 for (vit = vec->begin(); vit != vec->end(); vit++) { 924 if (*vit >= l) *vit = *vit - 1; 925 } 926 } 927 // Now the map 928 std::map<int, std::vector<int> >::iterator it; 929 for (it = lines.begin(); it != lines.end(); it++) { 930 for (vit = it->second.begin(); vit != it->second.end(); vit++) { 931 if (*vit >= l) *vit = *vit - 1; 932 } 933 } 934 // And the parent table 935 std::vector<std::pair<int, int> >::iterator vpit; 936 for (vpit = parent.begin(); vpit != parent.end(); vpit++) { 937 if (vpit->first >= l) vpit->first--; 938 if (vpit->second >= l) vpit->second--; 939 } 940 } 941 void remove(LinesToSimplify& lts) { 942 std::map<int, std::vector<int> >::iterator it; 943 for (it = lts.lines.begin(); it != lts.lines.end(); it++) { 944 std::vector<int>::iterator vit; 945 for (vit = it->second.begin(); vit != it->second.end(); vit++) { 946 remove(NULL, *vit, false); 947 } 948 } 949 } 950 void remove(std::vector<int>* v, int i, bool success = true) { 951 if (v != NULL) { 952 v->erase(std::remove(v->begin(), v->end(), i), v->end()); 953 } 954 std::map<int, std::vector<int> >::iterator it; 955 for (it = lines.begin(); it != lines.end(); it++) { 956 std::vector<int>* v = &(it->second); 957 v->erase(std::remove(v->begin(), v->end(), i), v->end()); 958 } 959 // Call on its parent 960 if (!success) { 961 std::vector<std::pair<int, int> >::iterator vpit; 962 for (vpit = parent.begin(); vpit != parent.end(); vpit++) { 963 if (vpit->first == i && vpit->second != i && vpit->second != -1) { 964 remove(v, vpit->second, false); 965 } 966 } 967 } 968 } 969 std::vector<int>* getLinesToSimplify() { 970 std::vector<int>* vec = new std::vector<int>(); 971 std::map<int, std::vector<int> >::iterator it; 972 for (it = lines.begin(); it != lines.end(); it++) { 973 std::vector<int>& svec = it->second; 974 vec->insert(vec->begin(), svec.begin(), svec.end()); 975 } 976 return vec; 977 } 978}; 979 980Document* expressionToDocument(const Expression* e); 981Document* annotationToDocument(const Annotation& ann); 982Document* tiexpressionToDocument(const Type& type, const Expression* e) { 983 DocumentList* dl = new DocumentList("", "", "", false); 984 switch (type.ti()) { 985 case Type::TI_PAR: 986 break; 987 case Type::TI_VAR: 988 dl->addStringToList("var "); 989 break; 990 } 991 if (type.ot() == Type::OT_OPTIONAL) dl->addStringToList("opt "); 992 if (type.st() == Type::ST_SET) dl->addStringToList("set of "); 993 if (e == NULL) { 994 switch (type.bt()) { 995 case Type::BT_INT: 996 dl->addStringToList("int"); 997 break; 998 case Type::BT_BOOL: 999 dl->addStringToList("bool"); 1000 break; 1001 case Type::BT_FLOAT: 1002 dl->addStringToList("float"); 1003 break; 1004 case Type::BT_STRING: 1005 dl->addStringToList("string"); 1006 break; 1007 case Type::BT_ANN: 1008 dl->addStringToList("ann"); 1009 break; 1010 case Type::BT_BOT: 1011 dl->addStringToList("bot"); 1012 break; 1013 case Type::BT_TOP: 1014 dl->addStringToList("top"); 1015 break; 1016 case Type::BT_UNKNOWN: 1017 dl->addStringToList("???"); 1018 break; 1019 } 1020 } else { 1021 dl->addDocumentToList(expressionToDocument(e)); 1022 } 1023 return dl; 1024} 1025 1026class ExpressionDocumentMapper { 1027public: 1028 typedef Document* ret; 1029 ret mapIntLit(const IntLit& il) { 1030 std::ostringstream oss; 1031 oss << il.v(); 1032 return new StringDocument(oss.str()); 1033 } 1034 ret mapFloatLit(const FloatLit& fl) { 1035 std::ostringstream oss; 1036 ppFloatVal(oss, fl.v()); 1037 return new StringDocument(oss.str()); 1038 } 1039 ret mapSetLit(const SetLit& sl) { 1040 DocumentList* dl; 1041 if (sl.isv()) { 1042 if (sl.isv()->size() == 0) { 1043 dl = new DocumentList("1..0", "", ""); 1044 } else if (sl.isv()->size() == 1) { 1045 dl = new DocumentList("", "..", ""); 1046 { 1047 std::ostringstream oss; 1048 oss << sl.isv()->min(0); 1049 dl->addDocumentToList(new StringDocument(oss.str())); 1050 } 1051 { 1052 std::ostringstream oss; 1053 oss << sl.isv()->max(0); 1054 dl->addDocumentToList(new StringDocument(oss.str())); 1055 } 1056 } else { 1057 dl = new DocumentList("{", ", ", "}", true); 1058 IntSetRanges isr(sl.isv()); 1059 for (Ranges::ToValues<IntSetRanges> isv(isr); isv(); ++isv) { 1060 std::ostringstream oss; 1061 oss << isv.val(); 1062 dl->addDocumentToList(new StringDocument(oss.str())); 1063 } 1064 } 1065 } else if (sl.fsv()) { 1066 if (sl.fsv()->size() == 0) { 1067 dl = new DocumentList("1.0..0.0", "", ""); 1068 } else if (sl.fsv()->size() == 1) { 1069 dl = new DocumentList("", "..", ""); 1070 { 1071 std::ostringstream oss; 1072 ppFloatVal(oss, sl.fsv()->min(0)); 1073 dl->addDocumentToList(new StringDocument(oss.str())); 1074 } 1075 { 1076 std::ostringstream oss; 1077 ppFloatVal(oss, sl.fsv()->max(0)); 1078 dl->addDocumentToList(new StringDocument(oss.str())); 1079 } 1080 } else { 1081 dl = new DocumentList("", "++", "", true); 1082 FloatSetRanges fsr(sl.fsv()); 1083 for (; fsr(); ++fsr) { 1084 std::ostringstream oss; 1085 ppFloatVal(oss, fsr.min()); 1086 oss << ".."; 1087 ppFloatVal(oss, fsr.max()); 1088 dl->addDocumentToList(new StringDocument(oss.str())); 1089 } 1090 } 1091 1092 } else { 1093 dl = new DocumentList("{", ", ", "}", true); 1094 for (unsigned int i = 0; i < sl.v().size(); i++) { 1095 dl->addDocumentToList(expressionToDocument((sl.v()[i]))); 1096 } 1097 } 1098 return dl; 1099 } 1100 ret mapBoolLit(const BoolLit& bl) { 1101 return new StringDocument(std::string(bl.v() ? "true" : "false")); 1102 } 1103 ret mapStringLit(const StringLit& sl) { 1104 std::ostringstream oss; 1105 oss << "\"" << Printer::escapeStringLit(sl.v()) << "\""; 1106 return new StringDocument(oss.str()); 1107 } 1108 ret mapId(const Id& id) { 1109 if (&id == constants().absent) return new StringDocument("<>"); 1110 if (id.idn() == -1) 1111 return new StringDocument(id.v().str()); 1112 else { 1113 std::ostringstream oss; 1114 oss << "X_INTRODUCED_" << id.idn() << "_"; 1115 return new StringDocument(oss.str()); 1116 } 1117 } 1118 ret mapTIId(const TIId& id) { return new StringDocument("$" + id.v().str()); } 1119 ret mapAnonVar(const AnonVar&) { return new StringDocument("_"); } 1120 ret mapArrayLit(const ArrayLit& al) { 1121 /// TODO: test multi-dimensional arrays handling 1122 DocumentList* dl; 1123 int n = al.dims(); 1124 if (n == 1 && al.min(0) == 1) { 1125 dl = new DocumentList("[", ", ", "]"); 1126 for (unsigned int i = 0; i < al.size(); i++) 1127 dl->addDocumentToList(expressionToDocument(al[i])); 1128 } else if (n == 2 && al.min(0) == 1 && al.min(1) == 1) { 1129 dl = new DocumentList("[| ", " | ", " |]"); 1130 for (int i = 0; i < al.max(0); i++) { 1131 DocumentList* row = new DocumentList("", ", ", ""); 1132 for (int j = 0; j < al.max(1); j++) { 1133 row->addDocumentToList(expressionToDocument(al[i * al.max(1) + j])); 1134 } 1135 dl->addDocumentToList(row); 1136 if (i != al.max(0) - 1) dl->addBreakPoint(true); // dont simplify 1137 } 1138 } else { 1139 dl = new DocumentList("", "", ""); 1140 std::stringstream oss; 1141 oss << "array" << n << "d"; 1142 dl->addStringToList(oss.str()); 1143 DocumentList* args = new DocumentList("(", ", ", ")"); 1144 1145 for (int i = 0; i < al.dims(); i++) { 1146 oss.str(""); 1147 oss << al.min(i) << ".." << al.max(i); 1148 args->addStringToList(oss.str()); 1149 } 1150 DocumentList* array = new DocumentList("[", ", ", "]"); 1151 for (unsigned int i = 0; i < al.size(); i++) 1152 array->addDocumentToList(expressionToDocument(al[i])); 1153 args->addDocumentToList(array); 1154 dl->addDocumentToList(args); 1155 } 1156 return dl; 1157 } 1158 ret mapArrayAccess(const ArrayAccess& aa) { 1159 DocumentList* dl = new DocumentList("", "", ""); 1160 1161 dl->addDocumentToList(expressionToDocument(aa.v())); 1162 DocumentList* args = new DocumentList("[", ", ", "]"); 1163 for (unsigned int i = 0; i < aa.idx().size(); i++) { 1164 args->addDocumentToList(expressionToDocument(aa.idx()[i])); 1165 } 1166 dl->addDocumentToList(args); 1167 return dl; 1168 } 1169 ret mapComprehension(const Comprehension& c) { 1170 std::ostringstream oss; 1171 DocumentList* dl; 1172 if (c.set()) 1173 dl = new DocumentList("{ ", " | ", " }"); 1174 else 1175 dl = new DocumentList("[ ", " | ", " ]"); 1176 dl->addDocumentToList(expressionToDocument(c.e())); 1177 DocumentList* head = new DocumentList("", " ", ""); 1178 DocumentList* generators = new DocumentList("", ", ", ""); 1179 for (int i = 0; i < c.n_generators(); i++) { 1180 DocumentList* gen = new DocumentList("", "", ""); 1181 DocumentList* idents = new DocumentList("", ", ", ""); 1182 for (int j = 0; j < c.n_decls(i); j++) { 1183 idents->addStringToList(c.decl(i, j)->id()->v().str()); 1184 } 1185 gen->addDocumentToList(idents); 1186 if (c.in(i) == NULL) { 1187 gen->addStringToList(" = "); 1188 gen->addDocumentToList(expressionToDocument(c.where(i))); 1189 } else { 1190 gen->addStringToList(" in "); 1191 gen->addDocumentToList(expressionToDocument(c.in(i))); 1192 if (c.where(i) != NULL) { 1193 gen->addStringToList(" where "); 1194 gen->addDocumentToList(expressionToDocument(c.where(i))); 1195 } 1196 } 1197 generators->addDocumentToList(gen); 1198 } 1199 head->addDocumentToList(generators); 1200 dl->addDocumentToList(head); 1201 1202 return dl; 1203 } 1204 ret mapITE(const ITE& ite) { 1205 DocumentList* dl = new DocumentList("", "", ""); 1206 for (int i = 0; i < ite.size(); i++) { 1207 std::string beg = (i == 0 ? "if " : " elseif "); 1208 dl->addStringToList(beg); 1209 dl->addDocumentToList(expressionToDocument(ite.e_if(i))); 1210 dl->addStringToList(" then "); 1211 1212 DocumentList* ifdoc = new DocumentList("", "", "", false); 1213 ifdoc->addBreakPoint(); 1214 ifdoc->addDocumentToList(expressionToDocument(ite.e_then(i))); 1215 dl->addDocumentToList(ifdoc); 1216 dl->addStringToList(" "); 1217 } 1218 dl->addBreakPoint(); 1219 dl->addStringToList("else "); 1220 1221 DocumentList* elsedoc = new DocumentList("", "", "", false); 1222 elsedoc->addBreakPoint(); 1223 elsedoc->addDocumentToList(expressionToDocument(ite.e_else())); 1224 dl->addDocumentToList(elsedoc); 1225 dl->addStringToList(" "); 1226 dl->addBreakPoint(); 1227 dl->addStringToList("endif"); 1228 1229 return dl; 1230 } 1231 ret mapBinOp(const BinOp& bo) { 1232 Parentheses ps = needParens(&bo, bo.lhs(), bo.rhs()); 1233 DocumentList* opLeft; 1234 DocumentList* dl; 1235 DocumentList* opRight; 1236 bool linebreak = false; 1237 if (ps & PN_LEFT) 1238 opLeft = new DocumentList("(", " ", ")"); 1239 else 1240 opLeft = new DocumentList("", " ", ""); 1241 opLeft->addDocumentToList(expressionToDocument(bo.lhs())); 1242 std::string op; 1243 switch (bo.op()) { 1244 case BOT_PLUS: 1245 op = "+"; 1246 break; 1247 case BOT_MINUS: 1248 op = "-"; 1249 break; 1250 case BOT_MULT: 1251 op = "*"; 1252 break; 1253 case BOT_POW: 1254 op = "^"; 1255 break; 1256 case BOT_DIV: 1257 op = "/"; 1258 break; 1259 case BOT_IDIV: 1260 op = " div "; 1261 break; 1262 case BOT_MOD: 1263 op = " mod "; 1264 break; 1265 case BOT_LE: 1266 op = " < "; 1267 break; 1268 case BOT_LQ: 1269 op = "<="; 1270 break; 1271 case BOT_GR: 1272 op = " > "; 1273 break; 1274 case BOT_GQ: 1275 op = ">="; 1276 break; 1277 case BOT_EQ: 1278 op = "=="; 1279 break; 1280 case BOT_NQ: 1281 op = "!="; 1282 break; 1283 case BOT_IN: 1284 op = " in "; 1285 break; 1286 case BOT_SUBSET: 1287 op = " subset "; 1288 break; 1289 case BOT_SUPERSET: 1290 op = " superset "; 1291 break; 1292 case BOT_UNION: 1293 op = " union "; 1294 break; 1295 case BOT_DIFF: 1296 op = " diff "; 1297 break; 1298 case BOT_SYMDIFF: 1299 op = " symdiff "; 1300 break; 1301 case BOT_INTERSECT: 1302 op = " intersect "; 1303 break; 1304 case BOT_PLUSPLUS: 1305 op = "++"; 1306 linebreak = true; 1307 break; 1308 case BOT_EQUIV: 1309 op = " <-> "; 1310 break; 1311 case BOT_IMPL: 1312 op = " -> "; 1313 break; 1314 case BOT_RIMPL: 1315 op = " <- "; 1316 break; 1317 case BOT_OR: 1318 op = " \\/ "; 1319 linebreak = true; 1320 break; 1321 case BOT_AND: 1322 op = " /\\ "; 1323 linebreak = true; 1324 break; 1325 case BOT_XOR: 1326 op = " xor "; 1327 break; 1328 case BOT_DOTDOT: 1329 op = ".."; 1330 break; 1331 default: 1332 assert(false); 1333 break; 1334 } 1335 dl = new DocumentList("", op, ""); 1336 1337 if (ps & PN_RIGHT) 1338 opRight = new DocumentList("(", " ", ")"); 1339 else 1340 opRight = new DocumentList("", "", ""); 1341 opRight->addDocumentToList(expressionToDocument(bo.rhs())); 1342 dl->addDocumentToList(opLeft); 1343 if (linebreak) dl->addBreakPoint(); 1344 dl->addDocumentToList(opRight); 1345 1346 return dl; 1347 } 1348 ret mapUnOp(const UnOp& uo) { 1349 DocumentList* dl = new DocumentList("", "", ""); 1350 std::string op; 1351 switch (uo.op()) { 1352 case UOT_NOT: 1353 op = "not "; 1354 break; 1355 case UOT_PLUS: 1356 op = "+"; 1357 break; 1358 case UOT_MINUS: 1359 op = "-"; 1360 break; 1361 default: 1362 assert(false); 1363 break; 1364 } 1365 dl->addStringToList(op); 1366 DocumentList* unop; 1367 bool needParen = (uo.e()->isa<BinOp>() || uo.e()->isa<UnOp>()); 1368 if (needParen) 1369 unop = new DocumentList("(", " ", ")"); 1370 else 1371 unop = new DocumentList("", " ", ""); 1372 1373 unop->addDocumentToList(expressionToDocument(uo.e())); 1374 dl->addDocumentToList(unop); 1375 return dl; 1376 } 1377 ret mapCall(const Call& c) { 1378 if (c.n_args() == 1) { 1379 /* 1380 * if we have only one argument, and this is an array comprehension, 1381 * we convert it into the following syntax 1382 * forall (f(i,j) | i in 1..10) 1383 * --> 1384 * forall (i in 1..10) (f(i,j)) 1385 */ 1386 1387 const Expression* e = c.arg(0); 1388 if (e->isa<Comprehension>()) { 1389 const Comprehension* com = e->cast<Comprehension>(); 1390 if (!com->set()) { 1391 DocumentList* dl = new DocumentList("", " ", ""); 1392 dl->addStringToList(c.id().str()); 1393 DocumentList* args = new DocumentList("", " ", "", false); 1394 DocumentList* generators = new DocumentList("", ", ", ""); 1395 1396 for (int i = 0; i < com->n_generators(); i++) { 1397 DocumentList* gen = new DocumentList("", "", ""); 1398 DocumentList* idents = new DocumentList("", ", ", ""); 1399 for (int j = 0; j < com->n_decls(i); j++) { 1400 idents->addStringToList(com->decl(i, j)->id()->v().str()); 1401 } 1402 gen->addDocumentToList(idents); 1403 if (com->in(i) == NULL) { 1404 gen->addStringToList(" = "); 1405 gen->addDocumentToList(expressionToDocument(com->where(i))); 1406 } else { 1407 gen->addStringToList(" in "); 1408 gen->addDocumentToList(expressionToDocument(com->in(i))); 1409 if (com->where(i) != NULL) { 1410 gen->addStringToList(" where "); 1411 gen->addDocumentToList(expressionToDocument(com->where(i))); 1412 } 1413 } 1414 generators->addDocumentToList(gen); 1415 } 1416 1417 args->addStringToList("("); 1418 args->addDocumentToList(generators); 1419 args->addStringToList(")"); 1420 1421 args->addStringToList("("); 1422 args->addBreakPoint(); 1423 args->addDocumentToList(expressionToDocument(com->e())); 1424 1425 dl->addDocumentToList(args); 1426 dl->addBreakPoint(); 1427 dl->addStringToList(")"); 1428 1429 return dl; 1430 } 1431 } 1432 } 1433 std::string beg = c.id().str() + "("; 1434 DocumentList* dl = new DocumentList(beg, ", ", ")"); 1435 for (unsigned int i = 0; i < c.n_args(); i++) { 1436 dl->addDocumentToList(expressionToDocument(c.arg(i))); 1437 } 1438 return dl; 1439 } 1440 ret mapVarDecl(const VarDecl& vd) { 1441 std::ostringstream oss; 1442 DocumentList* dl = new DocumentList("", "", ""); 1443 dl->addDocumentToList(expressionToDocument(vd.ti())); 1444 dl->addStringToList(": "); 1445 if (vd.id()->idn() == -1) { 1446 dl->addStringToList(vd.id()->v().str()); 1447 } else { 1448 std::ostringstream oss; 1449 oss << "X_INTRODUCED_" << vd.id()->idn() << "_"; 1450 dl->addStringToList(oss.str()); 1451 } 1452 1453 if (vd.introduced()) { 1454 dl->addStringToList(" ::var_is_introduced "); 1455 } 1456 if (!vd.ann().isEmpty()) { 1457 dl->addDocumentToList(annotationToDocument(vd.ann())); 1458 } 1459 if (vd.e()) { 1460 dl->addStringToList(" = "); 1461 dl->addDocumentToList(expressionToDocument(vd.e())); 1462 } 1463 return dl; 1464 } 1465 ret mapLet(const Let& l) { 1466 DocumentList* letin = new DocumentList("", "", "", false); 1467 DocumentList* lets = new DocumentList("", " ", "", true); 1468 DocumentList* inexpr = new DocumentList("", "", ""); 1469 bool ds = l.let().size() > 1; 1470 1471 for (unsigned int i = 0; i < l.let().size(); i++) { 1472 if (i != 0) lets->addBreakPoint(ds); 1473 DocumentList* exp = new DocumentList("", " ", ","); 1474 const Expression* li = l.let()[i]; 1475 if (!li->isa<VarDecl>()) exp->addStringToList("constraint"); 1476 exp->addDocumentToList(expressionToDocument(li)); 1477 lets->addDocumentToList(exp); 1478 } 1479 1480 inexpr->addDocumentToList(expressionToDocument(l.in())); 1481 letin->addBreakPoint(ds); 1482 letin->addDocumentToList(lets); 1483 1484 DocumentList* letin2 = new DocumentList("", "", "", false); 1485 1486 letin2->addBreakPoint(); 1487 letin2->addDocumentToList(inexpr); 1488 1489 DocumentList* dl = new DocumentList("", "", ""); 1490 dl->addStringToList("let {"); 1491 dl->addDocumentToList(letin); 1492 dl->addBreakPoint(ds); 1493 dl->addStringToList("} in ("); 1494 dl->addDocumentToList(letin2); 1495 // dl->addBreakPoint(); 1496 dl->addStringToList(")"); 1497 return dl; 1498 } 1499 ret mapTypeInst(const TypeInst& ti) { 1500 DocumentList* dl = new DocumentList("", "", ""); 1501 if (ti.isarray()) { 1502 dl->addStringToList("array ["); 1503 DocumentList* ran = new DocumentList("", ", ", ""); 1504 for (unsigned int i = 0; i < ti.ranges().size(); i++) { 1505 ran->addDocumentToList(tiexpressionToDocument(Type::parint(), ti.ranges()[i])); 1506 } 1507 dl->addDocumentToList(ran); 1508 dl->addStringToList("] of "); 1509 } 1510 dl->addDocumentToList(tiexpressionToDocument(ti.type(), ti.domain())); 1511 return dl; 1512 } 1513}; 1514 1515Document* annotationToDocument(const Annotation& ann) { 1516 DocumentList* dl = new DocumentList(" :: ", " :: ", ""); 1517 for (ExpressionSetIter it = ann.begin(); it != ann.end(); ++it) { 1518 dl->addDocumentToList(expressionToDocument(*it)); 1519 } 1520 return dl; 1521} 1522 1523Document* expressionToDocument(const Expression* e) { 1524 if (e == NULL) return new StringDocument("NULL"); 1525 ExpressionDocumentMapper esm; 1526 ExpressionMapper<ExpressionDocumentMapper> em(esm); 1527 DocumentList* dl = new DocumentList("", "", ""); 1528 Document* s = em.map(e); 1529 dl->addDocumentToList(s); 1530 if (!e->isa<VarDecl>() && !e->ann().isEmpty()) { 1531 dl->addDocumentToList(annotationToDocument(e->ann())); 1532 } 1533 return dl; 1534} 1535 1536class ItemDocumentMapper { 1537public: 1538 typedef Document* ret; 1539 ret mapIncludeI(const IncludeI& ii) { 1540 std::ostringstream oss; 1541 oss << "include \"" << ii.f() << "\";"; 1542 return new StringDocument(oss.str()); 1543 } 1544 ret mapVarDeclI(const VarDeclI& vi) { 1545 DocumentList* dl = new DocumentList("", " ", ";"); 1546 dl->addDocumentToList(expressionToDocument(vi.e())); 1547 return dl; 1548 } 1549 ret mapAssignI(const AssignI& ai) { 1550 DocumentList* dl = new DocumentList("", " = ", ";"); 1551 dl->addStringToList(ai.id().str()); 1552 dl->addDocumentToList(expressionToDocument(ai.e())); 1553 return dl; 1554 } 1555 ret mapConstraintI(const ConstraintI& ci) { 1556 DocumentList* dl = new DocumentList("constraint ", " ", ";"); 1557 dl->addDocumentToList(expressionToDocument(ci.e())); 1558 return dl; 1559 } 1560 ret mapSolveI(const SolveI& si) { 1561 DocumentList* dl = new DocumentList("", "", ";"); 1562 dl->addStringToList("solve"); 1563 if (!si.ann().isEmpty()) dl->addDocumentToList(annotationToDocument(si.ann())); 1564 switch (si.st()) { 1565 case SolveI::ST_SAT: 1566 dl->addStringToList(" satisfy"); 1567 break; 1568 case SolveI::ST_MIN: 1569 dl->addStringToList(" minimize "); 1570 dl->addDocumentToList(expressionToDocument(si.e())); 1571 break; 1572 case SolveI::ST_MAX: 1573 dl->addStringToList(" maximize "); 1574 dl->addDocumentToList(expressionToDocument(si.e())); 1575 break; 1576 } 1577 return dl; 1578 } 1579 ret mapOutputI(const OutputI& oi) { 1580 DocumentList* dl = new DocumentList("output ", " ", ";"); 1581 dl->addDocumentToList(expressionToDocument(oi.e())); 1582 return dl; 1583 } 1584 ret mapFunctionI(const FunctionI& fi) { 1585 DocumentList* dl; 1586 if (fi.ti()->type().isann() && fi.e() == NULL) { 1587 dl = new DocumentList("annotation ", " ", ";", false); 1588 } else if (fi.ti()->type() == Type::parbool()) { 1589 dl = new DocumentList("test ", "", ";", false); 1590 } else if (fi.ti()->type() == Type::varbool()) { 1591 dl = new DocumentList("predicate ", "", ";", false); 1592 } else { 1593 dl = new DocumentList("function ", "", ";", false); 1594 dl->addDocumentToList(expressionToDocument(fi.ti())); 1595 dl->addStringToList(": "); 1596 } 1597 dl->addStringToList(fi.id().str()); 1598 if (fi.params().size() > 0) { 1599 DocumentList* params = new DocumentList("(", ", ", ")"); 1600 for (unsigned int i = 0; i < fi.params().size(); i++) { 1601 DocumentList* par = new DocumentList("", "", ""); 1602 par->setUnbreakable(true); 1603 par->addDocumentToList(expressionToDocument(fi.params()[i])); 1604 params->addDocumentToList(par); 1605 } 1606 dl->addDocumentToList(params); 1607 } 1608 if (!fi.ann().isEmpty()) { 1609 dl->addDocumentToList(annotationToDocument(fi.ann())); 1610 } 1611 if (fi.e()) { 1612 dl->addStringToList(" = "); 1613 dl->addBreakPoint(); 1614 dl->addDocumentToList(expressionToDocument(fi.e())); 1615 } 1616 1617 return dl; 1618 } 1619}; 1620 1621class PrettyPrinter { 1622public: 1623 /* 1624 * \brief Constructor for class Pretty Printer 1625 * \param maxwidth (default 80) : number of rows 1626 * \param indentationBase : spaces that represent the atomic number of spaces 1627 * \param sim : whether we want to simplify the result 1628 * \param deepSimp : whether we want to simplify at each breakpoint or not 1629 */ 1630 PrettyPrinter(int _maxwidth = 80, int _indentationBase = 4, bool sim = false, 1631 bool deepSimp = false); 1632 1633 void print(Document* d); 1634 void print(std::ostream& os) const; 1635 1636private: 1637 int maxwidth; 1638 int indentationBase; 1639 int currentLine; 1640 int currentItem; 1641 std::vector<std::vector<Line> > items; 1642 std::vector<LinesToSimplify> linesToSimplify; 1643 std::vector<LinesToSimplify> linesNotToSimplify; 1644 bool simp; 1645 bool deeplySimp; 1646 1647 void addItem(); 1648 1649 void addLine(int indentation, bool bp = false, bool ds = false, int level = 0); 1650 static std::string printSpaces(int n); 1651 const std::vector<Line>& getCurrentItemLines() const; 1652 1653 void printDocument(Document* d, bool alignment, int startColAlignment, 1654 const std::string& before = "", const std::string& after = ""); 1655 void printDocList(DocumentList* d, int startColAlignment, const std::string& before = "", 1656 const std::string& after = ""); 1657 void printStringDoc(StringDocument* d, bool alignment, int startColAlignment, 1658 const std::string& before = "", const std::string& after = ""); 1659 void printString(const std::string& s, bool alignment, int startColAlignment); 1660 bool simplify(int item, int line, std::vector<int>* vec); 1661 void simplifyItem(int item); 1662}; 1663 1664void PrettyPrinter::print(Document* d) { 1665 addItem(); 1666 addLine(0); 1667 printDocument(d, true, 0); 1668 if (simp) simplifyItem(currentItem); 1669} 1670 1671PrettyPrinter::PrettyPrinter(int _maxwidth, int _indentationBase, bool sim, bool deepsim) { 1672 maxwidth = _maxwidth; 1673 indentationBase = _indentationBase; 1674 currentLine = -1; 1675 currentItem = -1; 1676 1677 simp = sim; 1678 deeplySimp = deepsim; 1679} 1680const std::vector<Line>& PrettyPrinter::getCurrentItemLines() const { return items[currentItem]; } 1681 1682void PrettyPrinter::addLine(int indentation, bool bp, bool simpl, int level) { 1683 items[currentItem].push_back(Line(indentation)); 1684 currentLine++; 1685 if (bp && deeplySimp) { 1686 linesToSimplify[currentItem].addLine(level, currentLine); 1687 if (!simpl) linesNotToSimplify[currentItem].addLine(0, currentLine); 1688 } 1689} 1690void PrettyPrinter::addItem() { 1691 items.push_back(std::vector<Line>()); 1692 linesToSimplify.push_back(LinesToSimplify()); 1693 linesNotToSimplify.push_back(LinesToSimplify()); 1694 currentItem++; 1695 currentLine = -1; 1696} 1697 1698void PrettyPrinter::print(std::ostream& os) const { 1699 std::vector<Line>::const_iterator it; 1700 int nItems = static_cast<int>(items.size()); 1701 for (int item = 0; item < nItems; item++) { 1702 for (it = items[item].begin(); it != items[item].end(); it++) { 1703 it->print(os); 1704 } 1705 // os << std::endl; 1706 } 1707} 1708std::string PrettyPrinter::printSpaces(int n) { 1709 std::string result; 1710 for (int i = 0; i < n; i++) { 1711 result += " "; 1712 } 1713 return result; 1714} 1715 1716void PrettyPrinter::printDocument(Document* d, bool alignment, int alignmentCol, 1717 const std::string& before, const std::string& after) { 1718 if (DocumentList* dl = dynamic_cast<DocumentList*>(d)) { 1719 printDocList(dl, alignmentCol, before, after); 1720 } else if (StringDocument* sd = dynamic_cast<StringDocument*>(d)) { 1721 printStringDoc(sd, alignment, alignmentCol, before, after); 1722 } else if (BreakPoint* bp = dynamic_cast<BreakPoint*>(d)) { 1723 printString(before, alignment, alignmentCol); 1724 addLine(alignmentCol, deeplySimp, !bp->getDontSimplify(), d->getLevel()); 1725 printString(after, alignment, alignmentCol); 1726 } else { 1727 throw InternalError("PrettyPrinter::print : Wrong type of document"); 1728 } 1729} 1730 1731void PrettyPrinter::printStringDoc(StringDocument* d, bool alignment, int alignmentCol, 1732 const std::string& before, const std::string& after) { 1733 std::string s; 1734 if (d != NULL) s = d->getString(); 1735 s = before + s + after; 1736 printString(s, alignment, alignmentCol); 1737} 1738 1739void PrettyPrinter::printString(const std::string& s, bool alignment, int alignmentCol) { 1740 Line& l = items[currentItem][currentLine]; 1741 int size = static_cast<int>(s.size()); 1742 if (size <= l.getSpaceLeft(maxwidth)) { 1743 l.addString(s); 1744 } else { 1745 int col = alignment && maxwidth - alignmentCol >= size ? alignmentCol : indentationBase; 1746 addLine(col); 1747 items[currentItem][currentLine].addString(s); 1748 } 1749} 1750 1751void PrettyPrinter::printDocList(DocumentList* d, int alignmentCol, const std::string& super_before, 1752 const std::string& super_after) { 1753 std::vector<Document*> ld = d->getDocs(); 1754 std::string beginToken = d->getBeginToken(); 1755 std::string separator = d->getSeparator(); 1756 std::string endToken = d->getEndToken(); 1757 bool _alignment = d->getAlignment(); 1758 if (d->getUnbreakable()) { 1759 addLine(alignmentCol); 1760 } 1761 int currentCol = items[currentItem][currentLine].getIndentation() + 1762 items[currentItem][currentLine].getLength(); 1763 int newAlignmentCol = 1764 _alignment ? currentCol + static_cast<int>(beginToken.size()) : alignmentCol; 1765 int vectorSize = static_cast<int>(ld.size()); 1766 int lastVisibleElementIndex; 1767 for (int i = 0; i < vectorSize; i++) { 1768 if (!dynamic_cast<BreakPoint*>(ld[i])) lastVisibleElementIndex = i; 1769 } 1770 if (vectorSize == 0) { 1771 printStringDoc(NULL, true, newAlignmentCol, super_before + beginToken, endToken + super_after); 1772 } 1773 for (int i = 0; i < vectorSize; i++) { 1774 Document* subdoc = ld[i]; 1775 bool bp = false; 1776 if (dynamic_cast<BreakPoint*>(subdoc)) { 1777 if (!_alignment) newAlignmentCol += indentationBase; 1778 bp = true; 1779 } 1780 std::string af, be; 1781 if (i != vectorSize - 1) { 1782 if (bp || lastVisibleElementIndex <= i) 1783 af = ""; 1784 else 1785 af = separator; 1786 } else { 1787 af = endToken + super_after; 1788 } 1789 if (i == 0) { 1790 be = super_before + beginToken; 1791 } else { 1792 be = ""; 1793 } 1794 printDocument(subdoc, _alignment, newAlignmentCol, be, af); 1795 } 1796 if (d->getUnbreakable()) { 1797 simplify(currentItem, currentLine, NULL); 1798 } 1799} 1800void PrettyPrinter::simplifyItem(int item) { 1801 linesToSimplify[item].remove(linesNotToSimplify[item]); 1802 std::vector<int>* vec = (linesToSimplify[item].getLinesToSimplify()); 1803 while (!vec->empty()) { 1804 if (!simplify(item, (*vec)[0], vec)) break; 1805 } 1806 delete vec; 1807} 1808 1809bool PrettyPrinter::simplify(int item, int line, std::vector<int>* vec) { 1810 if (line == 0) { 1811 linesToSimplify[item].remove(vec, line, false); 1812 return false; 1813 } 1814 if (items[item][line].getLength() > items[item][line - 1].getSpaceLeft(maxwidth)) { 1815 linesToSimplify[item].remove(vec, line, false); 1816 return false; 1817 } else { 1818 linesToSimplify[item].remove(vec, line, true); 1819 items[item][line - 1].concatenateLines(items[item][line]); 1820 items[item].erase(items[item].begin() + line); 1821 1822 linesToSimplify[item].decrementLine(vec, line); 1823 currentLine--; 1824 } 1825 1826 return true; 1827} 1828 1829Printer::Printer(std::ostream& os, int width, bool flatZinc, EnvI* env0) 1830 : env(env0), ism(NULL), printer(NULL), _os(os), _width(width), _flatZinc(flatZinc) {} 1831void Printer::init(void) { 1832 if (ism == NULL) { 1833 ism = new ItemDocumentMapper(); 1834 printer = new PrettyPrinter(_width, 4, true, true); 1835 } 1836} 1837Printer::~Printer(void) { 1838 delete printer; 1839 delete ism; 1840} 1841 1842void Printer::p(Document* d) { 1843 printer->print(d); 1844 printer->print(_os); 1845 delete printer; 1846 printer = new PrettyPrinter(_width, 4, true, true); 1847} 1848void Printer::p(const Item* i) { 1849 Document* d; 1850 switch (i->iid()) { 1851 case Item::II_INC: 1852 d = ism->mapIncludeI(*i->cast<IncludeI>()); 1853 break; 1854 case Item::II_VD: 1855 d = ism->mapVarDeclI(*i->cast<VarDeclI>()); 1856 break; 1857 case Item::II_ASN: 1858 d = ism->mapAssignI(*i->cast<AssignI>()); 1859 break; 1860 case Item::II_CON: 1861 d = ism->mapConstraintI(*i->cast<ConstraintI>()); 1862 break; 1863 case Item::II_SOL: 1864 d = ism->mapSolveI(*i->cast<SolveI>()); 1865 break; 1866 case Item::II_OUT: 1867 d = ism->mapOutputI(*i->cast<OutputI>()); 1868 break; 1869 case Item::II_FUN: 1870 d = ism->mapFunctionI(*i->cast<FunctionI>()); 1871 break; 1872 } 1873 p(d); 1874 delete d; 1875} 1876 1877void Printer::print(const Expression* e) { 1878 if (_width == 0) { 1879 PlainPrinter p(_os, _flatZinc, env); 1880 p.p(e); 1881 } else { 1882 init(); 1883 Document* d = expressionToDocument(e); 1884 p(d); 1885 delete d; 1886 } 1887} 1888void Printer::print(const Item* i) { 1889 if (_width == 0) { 1890 PlainPrinter p(_os, _flatZinc, env); 1891 p.p(i); 1892 } else { 1893 init(); 1894 p(i); 1895 } 1896} 1897void Printer::print(const Model* m) { 1898 if (_width == 0) { 1899 PlainPrinter p(_os, _flatZinc, env); 1900 for (unsigned int i = 0; i < m->size(); i++) { 1901 p.p((*m)[i]); 1902 } 1903 } else { 1904 init(); 1905 for (unsigned int i = 0; i < m->size(); i++) { 1906 p((*m)[i]); 1907 } 1908 } 1909} 1910 1911} // namespace MiniZinc 1912 1913void debugprint(MiniZinc::Expression* e) { std::cerr << *e << "\n"; } 1914void debugprint(MiniZinc::Item* i) { std::cerr << *i; } 1915void debugprint(MiniZinc::Model* m) { 1916 MiniZinc::Printer p(std::cerr, 0); 1917 p.print(m); 1918} 1919void debugprint(const MiniZinc::Location& loc) { std::cerr << loc << std::endl; }