From fe9c5c10d1722f4bd1f70996c209d293df6a38af Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Thu, 9 Dec 2021 20:56:50 -0500 Subject: [PATCH] [goos] support improper lists in pretty printer (#1001) --- common/goos/PrettyPrinter2.cpp | 26 +++++++++++++++++++------- test/test_pretty_print.cpp | 22 ++++++++++++++++++++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/common/goos/PrettyPrinter2.cpp b/common/goos/PrettyPrinter2.cpp index 782f06e080..102d790f10 100644 --- a/common/goos/PrettyPrinter2.cpp +++ b/common/goos/PrettyPrinter2.cpp @@ -26,13 +26,10 @@ struct Node { } Node(std::vector&& list, bool is_list) { - kind = is_list ? Kind::LIST : Kind::PAIR; - if (!is_list) { - assert(list.size() == 2); - } + kind = is_list ? Kind::LIST : Kind::IMPROPER_LIST; child_nodes = std::move(list); } - enum class Kind : u8 { ATOM, LIST, PAIR, INVALID } kind = Kind::INVALID; + enum class Kind : u8 { ATOM, LIST, IMPROPER_LIST, INVALID } kind = Kind::INVALID; std::vector child_nodes; std::string atom_str; @@ -51,7 +48,7 @@ struct Node { case Kind::ATOM: break; case Kind::LIST: - case Kind::PAIR: + case Kind::IMPROPER_LIST: assert(!child_nodes.empty()); for (auto& child : child_nodes) { child.link(this, bfs_order, depth + 1); @@ -122,7 +119,6 @@ Node to_node(const goos::Object& obj) { } } else { children.push_back(to_node(*to_print)); - assert(false); // untested return Node(std::move(children), false); } } @@ -147,6 +143,7 @@ void recompute_lengths(const std::vector& bfs_order) { case Node::Kind::ATOM: node->text_len = node->atom_str.length() + node->quoted; break; + case Node::Kind::IMPROPER_LIST: case Node::Kind::LIST: { if (node->break_list) { // special case compute first line length @@ -323,6 +320,7 @@ void append_node_to_string(const Node* node, case Node::Kind::ATOM: str.append(node->atom_str); break; + case Node::Kind::IMPROPER_LIST: case Node::Kind::LIST: if (node->break_list) { str.push_back('('); @@ -332,6 +330,10 @@ void append_node_to_string(const Node* node, int extra_indent = 0; for (; node_idx < node->top_line_count; node_idx++) { size_t s0 = str.length(); + if (node->kind == Node::Kind::IMPROPER_LIST && + &node->child_nodes.at(node_idx) == &node->child_nodes.back()) { + str.append(". "); + } append_node_to_string(&node->child_nodes.at(node_idx), str, 0, listing_indent + extra_indent); // extra_indent += (str.length() - s0); @@ -343,6 +345,13 @@ void append_node_to_string(const Node* node, } str.push_back('\n'); for (; node_idx < node->child_nodes.size(); node_idx++) { + if (node->kind == Node::Kind::IMPROPER_LIST && + &node->child_nodes.at(node_idx) == &node->child_nodes.back()) { + for (int i = 0; i < listing_indent; i++) { + str.push_back(' '); + } + str.append(".\n"); + } append_node_to_string(&node->child_nodes.at(node_idx), str, listing_indent, listing_indent); str.push_back('\n'); @@ -358,6 +367,9 @@ void append_node_to_string(const Node* node, int extra_indent = 1; int c0 = 0; for (auto& child : node->child_nodes) { + if (node->kind == Node::Kind::IMPROPER_LIST && &child == &node->child_nodes.back()) { + str.append(". "); + } size_t s0 = str.length(); append_node_to_string(&child, str, 0, listing_indent + extra_indent); str.push_back(' '); diff --git a/test/test_pretty_print.cpp b/test/test_pretty_print.cpp index d6f2f65dd0..1369b58c09 100644 --- a/test/test_pretty_print.cpp +++ b/test/test_pretty_print.cpp @@ -102,10 +102,10 @@ TEST(PrettyPrinter2, Debugging) { } namespace { -std::string pretty_print_v2(const std::string& str) { +std::string pretty_print_v2(const std::string& str, int line_length = 110) { auto obj = pretty_print::get_pretty_printer_reader().read_from_string(str).as_pair()->cdr.as_pair()->car; - return pretty_print::to_string(obj); + return pretty_print::to_string(obj, line_length); } } // namespace @@ -240,3 +240,21 @@ TEST(PrettyPrint2, ParenWayOutToTheRight) { ) ))"); } + +TEST(PrettyPrint2, ImproperList) { + std::string code = "( ( a . b) ( c . d ) ( e f . g) . #f )"; + EXPECT_EQ(pretty_print_v2(code), "((a . b) (c . d) (e f . g) . #f)"); +} + +TEST(PrettyPrint2, ImproperListMultiLine) { + std::string code = + "( ( asdfasfdasdf . b) ( casdfsadfasdf . dsadfasfdsf ) ( esdfasdf fdasfsadf . gdfasfd) . " + "#f )"; + EXPECT_EQ(pretty_print_v2(code, 40), + "((asdfasfdasdf . b)\n" + " (casdfsadfasdf . dsadfasfdsf)\n" + " (esdfasdf fdasfsadf . gdfasfd)\n" + " .\n" + " #f\n" + " )"); +} \ No newline at end of file