aboutsummaryrefslogtreecommitdiffstats
path: root/src/pprint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pprint.cpp')
-rw-r--r--src/pprint.cpp107
1 files changed, 87 insertions, 20 deletions
diff --git a/src/pprint.cpp b/src/pprint.cpp
index 391609a..76796d7 100644
--- a/src/pprint.cpp
+++ b/src/pprint.cpp
@@ -73,34 +73,101 @@ operator<<(ostream& out, const AST* ast)
return out << "?";
}
+enum TupleStyle {
+ STYLE_ONE_LINE, // Entire tuple printed on one line
+ STYLE_ALIGN, // Align all elements aligned after opening '('
+ STYLE_CALL // Call with all arguments aligned after head
+};
+
+static bool
+can_one_line(const AST* ast, const unsigned max_width, unsigned& width, unsigned& depth)
+{
+ static const unsigned MAX_DEPTH = 3;
+
+ ostringstream ss;
+ ss << ast;
+ if ((width += ss.str().length()) >= max_width)
+ return false;
+
+ const ATuple* tup = ast->to<const ATuple*>();
+ if (tup) {
+ if (++depth >= MAX_DEPTH)
+ return false;
+
+ for (ATuple::const_iterator i = tup->begin(); i != tup->end(); ++i) {
+ ostringstream ss;
+ ss << *i;
+ width += ss.str().length();
+ if (!can_one_line(*i, max_width, width, depth))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static TupleStyle
+tuple_style(const ATuple* tup, const unsigned max_width, unsigned& indent)
+{
+ unsigned depth = 0;
+ unsigned width = indent;
+ if (can_one_line(tup, max_width, width, depth))
+ return STYLE_ONE_LINE;
+
+ if (tup->to<const ADef*>() || tup->to<const AFn*>()) {
+ indent += 2;
+ return STYLE_CALL;
+ }
+
+ if (tup->to<const ACall*>()) {
+ indent += tup->head()->str().length() + 1;
+ return STYLE_CALL;
+ }
+
+ return STYLE_ALIGN;
+}
+
+static void
+newline(ostream& out, unsigned indent)
+{
+ out << endl;
+ for (unsigned i = 0; i < indent; ++i)
+ out << " ";
+}
+
void
pprint_internal(ostream& out, const AST* ast, unsigned indent)
{
const ATuple* tup = ast->to<const ATuple*>();
- if (tup && !tup->empty()) {
- ATuple::const_iterator i = tup->begin() + 1;
- const string head = tup->head()->str();
- const ASymbol* headSym = tup->head()->to<const ASymbol*>();
+ if (tup) {
out << "(";
- pprint_internal(out, tup->head(), indent);
- unsigned child_indent = indent;
- if (tup->size() > 1) {
- out << " ";
- if (headSym && (headSym->cppstr == "fn" || headSym->cppstr == "def")) {
- out << *i;
- child_indent = indent + 2;
- } else {
- child_indent += head.length() + 2;
- pprint_internal(out, *i, child_indent);
+ unsigned child_indent = indent + 1;
+ ATuple::const_iterator i = tup->begin();
+ if (i != tup->end()) {
+ const TupleStyle style = tuple_style(tup, 80, child_indent);
+ pprint_internal(out, *i++, indent + 1); // Print head
+ switch (style) {
+ case STYLE_ONE_LINE:
+ while (i != tup->end())
+ out << " " << *i++;
+ break;
+ case STYLE_ALIGN:
+ while (i != tup->end()) {
+ newline(out, indent + 1);
+ pprint_internal(out, *i++, child_indent);
+ }
+ break;
+ case STYLE_CALL:
+ out << " ";
+ pprint_internal(out, *i, child_indent); // Print first argument
+ while (++i != tup->end()) {
+ newline(out, child_indent);
+ pprint_internal(out, *i, child_indent);
+ }
+ break;
}
}
- while (++i != tup->end()) {
- out << endl << string().insert(0, child_indent, ' ');
- pprint_internal(out, *i, child_indent);
- }
out << ")";
- if (headSym && (headSym->cppstr == "fn" || headSym->cppstr == "def"))
- out << endl << string().insert(0, indent + 2, ' ');
} else {
out << ast;
}