/* Resp Serialisation * Copyright (C) 2008-2009 David Robillard * * Resp is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * Resp is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Resp. If not, see . */ /** @file * @brief Pretty-print AST expressions */ #include "resp.hpp" ostream& print_to(ostream& out, const AST* ast, unsigned indent, CEnv* cenv, bool types); static void newline(ostream& out, unsigned indent) { out << endl; for (unsigned i = 0; i < indent; ++i) out << " "; } ostream& print_tuple(ostream& out, const ATuple* tup, ATuple::const_iterator i, unsigned indent, bool newlines, CEnv* cenv, bool types, bool elem_types) { for (; i != tup->end(); ) { ATuple::const_iterator next = i; ++next; print_to(out, *i, newlines ? indent + 2 : indent, cenv, types); if (elem_types) out << " :" << cenv->tsubst.apply(cenv->tenv.var(*i)); if (next != tup->end()) { if (newlines) newline(out, indent + 2); else out << " "; } i = next; } return (out << ")"); } ostream& print_to(ostream& out, const AST* ast, unsigned indent, CEnv* cenv, bool types) { switch (ast->tag()) { case T_UNKNOWN: return out << "?"; case T_TYPE: { const AType* type = ast->as_type(); switch (type->kind) { case AType::VAR: return out << "?" << type->id; case AType::NAME: return out << type->head(); case AType::PRIM: return out << type->head(); case AType::DOTS: return out << "..."; case AType::EXPR: break; // will catch Tuple case below } } case T_TUPLE: { const ATuple* tup = ast->as_tuple(); out << "("; ATuple::const_iterator i = tup->begin(); std::string form = ""; if (i != tup->end()) { const ASymbol* sym = (*i)->to_symbol(); if (sym) { form = sym->cppstr; } else { const ALexeme* lexeme = (*i)->to_lexeme(); if (lexeme) form = lexeme->cppstr; } } if (form == "def") { out << (*i++) << " "; // Print symbol (possibly with type annotation) const AST* sym = *i++; out << sym; if (types) out << " :" << cenv->tsubst.apply(cenv->tenv.var(sym)); // Print value on following lines, indented newline(out, indent + 2); return print_tuple(out, tup, i, indent, true, cenv, types, false); } else if (form == "fn") { out << (*i++) << " "; const ATuple* pat = (*i++)->as_tuple(); // Print prototype (possibly with parameter type annotations) out << "("; print_tuple(out, pat, pat->begin(), indent, false, cenv, types, types); // Print body expression(s) on following lines, indented newline(out, indent + 2); return print_tuple(out, tup, i, indent + 2, true, cenv, types, false); } else if (form == "if") { out << (*i++) << " "; // Print each condition and consequent pair separated by blank lines for (; i != tup->end(); ) { ATuple::const_iterator next = i; ++next; print_to(out, *i, indent + 2, cenv, types); if (next != tup->end()) { newline(out, indent + 2); print_to(out, *next++, indent + 2, cenv, types); newline(out, 0); newline(out, indent + 2); } i = next; } return out; } else { return print_tuple(out, tup, i, indent + 1, false, cenv, types, false); } break; } case T_BOOL: return out << showpoint << ((const ALiteral*)ast)->val; case T_FLOAT: return out << showpoint << ((const ALiteral*)ast)->val; case T_INT32: return out << showpoint << ((const ALiteral*)ast)->val; case T_LEXEME: return out << ((const ALexeme*)ast)->cppstr; case T_STRING: return out << '"' << ((const AString*)ast)->cppstr << '"'; case T_SYMBOL: return out << ((const ASymbol*)ast)->cppstr; } return out << "?"; } ostream& operator<<(ostream& out, const AST* ast) { return print_to(out, ast, 0, NULL, false); } /// Pretty-print @a ast to @a out void pprint(ostream& out, const AST* ast, CEnv* cenv, bool types) { print_to(out, ast, 0, cenv, types); out << endl; }