diff options
Diffstat (limited to 'src/pprint.cpp')
-rw-r--r-- | src/pprint.cpp | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/pprint.cpp b/src/pprint.cpp new file mode 100644 index 0000000..04e3401 --- /dev/null +++ b/src/pprint.cpp @@ -0,0 +1,97 @@ +/* Tuplr Serialisation + * Copyright (C) 2008-2009 David Robillard <dave@drobilla.net> + * + * Tuplr 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. + * + * Tuplr 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 Tuplr. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "tuplr.hpp" + +ostream& +operator<<(ostream& out, const AST* ast) +{ + const ALiteral<float>* flit = ast->to<const ALiteral<float>*>(); + if (flit) + return out << showpoint << flit->val; + + const ALiteral<int32_t>* ilit = ast->to<const ALiteral<int32_t>*>(); + if (ilit) + return out << ilit->val; + + const ALiteral<bool>* blit = ast->to<const ALiteral<bool>*>(); + if (blit) + return out << (blit->val ? "#t" : "#f"); + + const ASymbol* sym = ast->to<const ASymbol*>(); + if (sym) + return out << sym->cppstr; + + const AType* type = ast->to<const AType*>(); + if (type) { + switch (type->kind) { + case AType::VAR: return out << "?" << type->id; + case AType::PRIM: return out << type->at(0); + case AType::EXPR: break; // will catch Tuple case below + } + } + + const ATuple* tup = ast->to<const ATuple*>(); + if (tup) { + out << "("; + for (size_t i = 0; i != tup->size(); ++i) + out << tup->at(i) << ((i != tup->size() - 1) ? " " : ""); + return out << ")"; + } + + return out << "?"; +} + +void +pprint_internal(ostream& out, const AST* ast, unsigned indent) +{ + const ATuple* tup = ast->to<const ATuple*>(); + if (tup && tup->size() > 0) { + const string head = tup->at(0)->str(); + ASymbol* headSym = tup->at(0)->to<ASymbol*>(); + out << "("; + pprint_internal(out, tup->at(0), indent); + unsigned child_indent = indent; + if (tup->size() > 1) { + out << " "; + if (headSym && headSym->cppstr == "fn") { + out << tup->at(1); + child_indent = indent + 4; + } else { + child_indent += head.length() + 1; + pprint_internal(out, tup->at(1), child_indent); + } + } + for (size_t i = 2; i < tup->size(); ++i) { + out << endl << string().insert(0, child_indent, ' '); + pprint_internal(out, tup->at(i), child_indent); + } + out << ")"; + if (headSym && headSym->cppstr == "fn") + out << endl << string().insert(0, indent + 4, ' '); + } else { + out << ast; + } +} + +void +pprint(ostream& out, const AST* ast) +{ + pprint_internal(out, ast, 0); + out << endl; +} + |