/* * Copyright (C) 2023 Riyyi * * SPDX-License-Identifier: MIT */ #include // std::next #include // std::static_pointer_cast #include #include "ruc/format/format.h" #include "ast.h" #include "error.h" #include "lexer.h" #include "printer.h" #include "types.h" #include "util.h" namespace blaze { Printer::Printer() { } Printer::~Printer() { } // ----------------------------------------- std::string Printer::print(ValuePtr node, bool print_readably) { if (Error::the().hasAnyError()) { init(); printError(); return m_print; } return printNoErrorCheck(node, print_readably); } std::string Printer::printNoErrorCheck(ValuePtr node, bool print_readably) { init(); if (node == nullptr) { return {}; } printImpl(node, print_readably); return m_print; } // ----------------------------------------- void Printer::init() { m_first_node = true; m_previous_node_is_list = false; m_print = ""; } void Printer::printImpl(ValuePtr node, bool print_readably) { auto printSpacing = [this]() -> void { if (!m_first_node && !m_previous_node_is_list) { m_print += ' '; } }; Value* node_raw_ptr = node.get(); if (is(node_raw_ptr)) { printSpacing(); m_print += (is(node_raw_ptr)) ? '(' : '['; m_first_node = false; m_previous_node_is_list = true; auto nodes = std::static_pointer_cast(node)->nodesRead(); for (auto node : nodes) { printImpl(node, print_readably); m_previous_node_is_list = false; } m_print += (is(node_raw_ptr)) ? ')' : ']'; } else if (is(node_raw_ptr)) { printSpacing(); m_print += "{"; m_first_node = false; m_previous_node_is_list = true; auto elements = std::static_pointer_cast(node)->elements(); for (auto it = elements.begin(); it != elements.end(); ++it) { m_print += ::format("{} ", (it->first.front() == 0x7f) ? ":" + it->first.substr(1) : '"' + it->first + '"'); // 127 printImpl(it->second, print_readably); if (!isLast(it, elements)) { m_print += ' '; } } m_previous_node_is_list = false; m_print += '}'; } else if (is(node_raw_ptr)) { std::string text = std::static_pointer_cast(node)->data(); if (print_readably) { text = replaceAll(text, "\\", "\\\\"); text = replaceAll(text, "\"", "\\\""); text = replaceAll(text, "\n", "\\n"); text = "\"" + text + "\""; } printSpacing(); m_print += ::format("{}", text); } else if (is(node_raw_ptr)) { printSpacing(); m_print += ::format(":{}", std::static_pointer_cast(node)->keyword().substr(1)); } else if (is(node_raw_ptr)) { printSpacing(); m_print += ::format("{}", std::static_pointer_cast(node)->number()); } else if (is(node_raw_ptr)) { printSpacing(); std::string value; switch (std::static_pointer_cast(node)->state()) { case Constant::Nil: value = "nil"; break; case Constant::True: value = "true"; break; case Constant::False: value = "false"; break; } m_print += ::format("{}", value); } else if (is(node_raw_ptr)) { printSpacing(); m_print += ::format("{}", std::static_pointer_cast(node)->symbol()); } else if (is(node_raw_ptr)) { printSpacing(); m_print += ::format("#({})", std::static_pointer_cast(node)->name()); } else if (is(node_raw_ptr)) { printSpacing(); m_print += ::format("#({:p})", node_raw_ptr); } else if (is(node_raw_ptr)) { printSpacing(); m_print += ::format("#({:p})", node_raw_ptr); } else if (is(node_raw_ptr)) { printSpacing(); m_print += "(atom "; printImpl(std::static_pointer_cast(node)->deref(), print_readably); m_print += ")"; } } void Printer::printError() { m_print = "Error: "; if (Error::the().hasTokenError()) { Token error = Error::the().tokenError(); m_print += ::format("{}", error.symbol); } else if (Error::the().hasOtherError()) { std::string error = Error::the().otherError(); m_print += ::format("{}", error); } else if (Error::the().hasException()) { ValuePtr error = Error::the().exception(); m_print += ::format("{}", error); } } } // namespace blaze