#include #include #include #include #include #include "ktype.h" #include "show.h" #include "util.h" #include "log.h" #include "file.h" bool color_enabled(const std::ostream& os) { // Function-local statics: isatty is asked once per descriptor, on first // use, so there is no static-initialization-order question and no syscall // per colour written. static const bool no_color = [] { const char* v = std::getenv("NO_COLOR"); return v != nullptr && v[0] != '\0'; }(); static const bool tty_out = isatty(fileno(stdout)) != 0; static const bool tty_err = isatty(fileno(stderr)) != 0; if (no_color) { return false; } if (&os == &std::cout) { return tty_out; } if (&os == &std::cerr || &os == &std::clog) { return tty_err; } return false; } std::ostream& operator<<(std::ostream& os, const Color& color) { if (color_enabled(os)) { os << color.code(); } return os; } std::ostream& msg(Locator loc) { std::cout << blue << loc.abbrev(false) << black << " "; return std::cout; } std::ostream& fmsg(Locator loc) { std::cout << blue << loc.abbrev(false) << black << kall << ktype << kindex << kreplaced << " "; return std::cout; } // std::vector std::ostream& operator<<(std::ostream& os, const std::vector& ns) { if (!ns.empty()) { auto rest = std::vector(ns.begin() + 1, ns.end()); os << ns[0]; for (auto n : rest) { os << ", " << n; } } return os; } // strings_t std::ostream& operator<<(std::ostream& os, const strings_t& ss) { if (!ss.empty()) { for (const std::string& s : ss) { os << "<" << s << ">"; } } return os; } // std::vector std::ostream& operator<<(std::ostream& os, const std::vector& pp) { if (!pp.empty()) { for (const fs::path& p : pp) { os << "<" << p.string() << ">"; } } return os; } // std::map std::ostream& operator<<(std::ostream& os, const std::map& sm) { size_t name_length = 0; for (auto [k,v] : sm) { name_length = std::max(k.size(), name_length); } for (auto [k,v] : sm) { os << std::setfill(' ') << " " << std::setw(name_length) << k << sp_arrow << " " << display_string(v) << "\n"; } return os; } // Katom iterator pair std::ostream& operator<<(std::ostream& os, const std::pair& iters) { for (auto e = iters.first; e < iters.second; e++) { std::cout << e; } std::cout << "\n"; return os; } // Locator std::ostream& operator<<(std::ostream& os, const Locator& loc) { os << loc.str(); return os; } // Katom std::string subscript(int n) { strings_t chars { "\u2080", "\u2081", "\u2082", "\u2083", "\u2084", "\u2085", "\u2086", "\u2087", "\u2088", "\u2089" }; std::string prefix {}; if (n < 0) prefix = "-"; std::string sn {std::to_string(std::abs(n))}; std::string result { prefix }; for (unsigned int i = 0; i < sn.size(); i++) { std::string d {sn[i]}; result += chars[std::stoi(d)]; } return result; } void os_char(std::ostream& os, katom_t type, unsigned char c) { if (type == katom_t::eval_result) { os << c; } else if ((Katom::show_all || Katom::show_whitespace) and c == ' ') { if (is_active(type)) os << boldgreen; const std::string space_s { "\u00B7" }; os << space_s; if (is_active(type)) os << black; } else if ((Katom::show_all || Katom::show_whitespace) and c == '\n') { if (is_active(type)) os << boldgreen; os << "/"; if (is_active(type)) os << black; } else if (c != '\n') os << c; } void os_body(std::ostream& os, const Katom& k) { bool bracketed = true; if (k.is_whitespace() || k.is_word() || k.is_text() || k.is_literal() || k.is_nonascii()) { bracketed = Katom::show_all; } if (bracketed) os << left_bracket; for (auto c : k.m_text) { os_char(os, k.m_type, c); } if (bracketed) { if (Katom::show_index) { os << subscript(k.m_index); } if (Katom::show_type){ if (Katom::show_index) { os << "."; } if (k.m_initial_type != k.m_type) { os << subscript(static_cast(k.m_initial_type)) << right_arrow; } os << subscript(static_cast(k.m_type)); } os << right_bracket; } } std::ostream& operator<<(std::ostream& os, const Katom& k) { //const std::string space_s { "\u2423" }; /// const std::string space_s { "\u00B7" }; // const std::string tab { "\u2023" }; // const std::string left_index { "\u27EA" }; // const std::string right_index { "\u27EB" }; // const std::string diamond { "\u2B29" }; //bool in_red = mark_as_error(k.m_type); //if (k.m_type == katom_t::ignored) // show_type = false; //if (in_red) //if (is_error(k.m_type)) // os << red; if (k.m_type == katom_t::replaced) { os << blue; // cyan; } else if (k.m_type == katom_t::ignored) { os << yellow; } //else if (k.m_type == katom_t::literal) // os << green; else { os << black; } if (is_active(k.m_type) or (Katom::show_replaced and (k.m_type == katom_t::replaced)) or (Katom::show_ignored and (k.m_type == katom_t::ignored))) { os_body(os, k); if (k.m_initial_type == katom_t::newline || (k.m_type == katom_t::ws_added && k.m_text == "\n")) { os << "\n"; } } //os << black; return os; } katom_list abbrev(const katom_list& ks, unsigned int max_length) { if (ks.size() > max_length) { katom_list result(ks.begin(), (ks.begin())+(max_length)); Katom ellipsis = Katom("[...]", katom_t::word, Locator()); result.push_back(ellipsis); result.push_back(ks.back()); std::for_each(result.begin(), result.end(), [](Katom& k) { if (k.m_type == katom_t::newline) { //std::cout << "NEWLINE\n"; k.m_type = katom_t::word; k.m_text = "/"; k.m_src = "/"; k.m_initial_type = katom_t::word; } }); return result; } else { katom_list result(ks.begin(), ks.end()); std::for_each(result.begin(), result.end(), [](Katom& k) { if (k.m_type == katom_t::newline) { //std::cout << "NEWLINE\n"; k.m_type = katom_t::word; k.m_text = "/"; k.m_initial_type = katom_t::word; } }); return result; } } std::ostream& operator<<(std::ostream& os, const katom_lists& ks) { //os << double_bar; //os << red < "|" << black; for (const auto& k : ks) { os << left_double_bracket << abbrev(k) << right_double_bracket << " "; //os << k << red << "|" << black; } // os << "\n"; return os; } std::ostream& operator<<(std::ostream& os, const katom_ptr& k) { os << *k; return os; } std::ostream& operator<<(std::ostream& os, const katom_iter& k) { os << *k; return os; } std::ostream& operator<<(std::ostream& os, const std::vector& ks) { for (const auto& k : ks) { os << k; } return os; } std::ostream& operator<<(std::ostream& os, const std::vector& ks) { for (const auto& k : ks) { os << *k; } return os; } std::ostream &kindex(std::ostream &os) { Katom::show_index = true; return os; } std::ostream &ktype(std::ostream &os) { Katom::show_type = true; return os; } std::ostream &kws(std::ostream &os) { Katom::show_whitespace = true; return os; } std::ostream &kall(std::ostream &os) { Katom::show_all = true; return os; } std::ostream &kreplaced(std::ostream &os) { Katom::show_replaced = true; return os; } std::ostream &kignored(std::ostream &os) { Katom::show_ignored = true; return os; } std::ostream &kreset(std::ostream &os) { Katom::show_index = false; Katom::show_type = false; Katom::show_all = false; Katom::show_replaced = false; Katom::show_ignored = false; Katom::show_whitespace = false; os << black; return os; } /* std::ostream& operator<<(std::ostream& os, const std::vector ks) { std::ranges::copy(ks, std::ostream_iterator(os, "")); return os; } */ // Argtype std::ostream& operator<<(std::ostream& os, const Argtype& a) { return os << left_bracket << "\U0001D504" << broken_bar << a.m_name << broken_bar << a.m_symbolic_pattern << broken_bar << a.m_count << broken_bar << a.m_mincount << broken_bar << a.m_maxcount << right_bracket; } // Parameter std::ostream& operator<<(std::ostream& os, const Parameter& arg) { os << left_bracket << "\U0001D513" << broken_bar; if (arg.m_optional) os << ":"; os << arg.m_name << "." << arg.m_argtype.m_name; //if (arg.m_default.size() != 0) if (!arg.m_default.empty()) { os << broken_bar << arg.m_default; } os << right_bracket; return os; } // std::vector std::ostream& operator<<(std::ostream& os, const std::vector& as) { for (const auto& a : as) { os << a; } return os; } // Parameter_set std::ostream& operator<<(std::ostream& os, const Parameter_set& as) { os << left_bracket << "\U0001D513\U0001D530" << broken_bar << as.m_positional.size() << broken_bar << as.m_optional.size() << broken_bar // << (as.m_rest.undefined() ? "-" : "+") << (as.m_rest.empty() ? "-" : "+") << broken_bar << "[" << as.m_katoms.size() << "]" << right_bracket; return os; } // Var std::ostream& operator<<(std::ostream& os, const Var& v) { os << "<" << v.m_name << ">"; return os; } // Frame std::ostream& operator<<(std::ostream& os, const Frame& f) { os << "{"; // for (auto [k,v] : f.m_vars) { // os << v; // } os << join(f.names(), "|"); os << "}"; return os; } // State std::ostream& operator<<(std::ostream& os, const State& s) { //for (int i = s.m_frames.size() - 1; i != 0; --i) { for (auto f : s.m_frames) { os << f << "\n"; } return os; } // Klammer std::ostream& operator<<(std::ostream& os, const Klammer& k) { std::string targets = join(k.get_target_names(), ","s); os << left_bracket << "\U0001D50E" << broken_bar << k.m_name << broken_bar << "p" << k.m_parameters.m_positional.size() << broken_bar << "o" << k.m_parameters.m_optional.size() << broken_bar << (targets.empty() ? "?" : targets) << right_bracket; return os; } // Klammer::variable_map_t std::ostream& operator<<(std::ostream& os, const Klammer::variable_map_t& vm) { for (auto [k, v] : vm) { os << " " << k << sp_arrow << v << "\n"; } return os; } // Klammer::components std::string katom_type_name(katom_t type) { // Could cache, but why bother - only for kdesc. for (auto t : katom_types) { if (t.m_type == type) { return t.m_name; } } throw Internal_error("Unknown katom_t: " + std::to_string((int)type)); } std::ostream& operator<<(std::ostream& os, const Klammer::components& kc) { std::string del = " "; auto [target, deftype, parameters, body, varmap, locator] = kc; os << std::setw(4) << target << del // << katom_types[(int)deftype].m_name << del << katom_type_name(deftype) << del << parameters << del << kall << ktype << red << body << del << locator; return os; } // Klammer_registry std::ostream& operator<<(std::ostream& os, const Klammer_registry& ks) { for (const auto& klam : ks.m_klammers) { for (const auto& [k,v] : klam.second.m_defloc) { os << " " << k << sp_arrow << v << "\n"; } //klam.second.m_defloc.str() << "\n"; std::cout << " " << klam.first << sp_arrow << klam.second << " " << "\n"; } return os; } // Target void show_arrow_pair(std::ostream& os, std::pair transform) { os << transform.first << sp_arrow << transform.second; } std::ostream& operator<<(std::ostream& os, const Target& t) { os << "<\U0001D517" << broken_bar << t.m_name << broken_bar << t.m_desc << broken_bar; for (const auto& i : t.m_includes) { os << i << right_arrow << t.m_name << broken_bar; } for (const auto& p : t.m_provides) { os << t.m_name << right_arrow << p << broken_bar; } os << ">"; return os; } // Target_registry std::ostream& operator<<(std::ostream& os, const Target_registry& ts) { size_t width = 0; for (const auto& t : ts.m_targets) { width = std::max(width, t.first.size()); } for (const auto& [name, target] : ts.m_targets) { os << std::setw(width) << name << sp_arrow << target << "\n"; } return os; } // Klammerset std::ostream& operator<<(std::ostream& os, const Klammerset& ks) { os << "<\U0001D516" << broken_bar << ks.m_symbol << broken_bar << ks.m_desc; if (!ks.m_date.empty()) { os << broken_bar << ks.m_date; } if (!ks.m_requires.empty()) { os << broken_bar << "requires " << join(ks.m_requires, " / "); } if (!ks.m_files.empty()) { os << broken_bar << join(ks.m_files, " / "); } os << ">"; return os; } // Klammerset_registry std::ostream& operator<<(std::ostream& os, const Klammerset_registry& kr) { size_t width = 0; for (const auto& k : kr.m_klammersets) { width = std::max(width, k.first.size()); } for (const auto& [symbol, klammerset] : kr.m_klammersets) { os << std::setw(width) << symbol << sp_arrow << klammerset << "\n"; } return os; } // Machine std::string describe_sources(Machine m) { std::stringstream ss {}; for (auto s : m.m_sources) { if (std::holds_alternative(s)) { ss << " String: " << trim(std::get(s)) << "\n"; } else { ss << " Filename: " << std::get(s).string() << "\n"; } } return ss.str(); } std::string label(std::string name, int count) { std::stringstream ss {}; ss << " " << name << " (" << count << "):\n"; return ss.str(); } std::ostream& operator<<(std::ostream& os, const Machine& m) { std::string argtypes_desc = m.m_argtypes.describe(false, 8); std::string state_desc = m.m_state.describe(false, 3); std::string targets_desc = m.m_targets.describe(4); std::string klammersets_desc = m.m_klammersets.describe(4); std::string option_sets_desc = m.m_option_sets.describe(4); std::string klammer_desc = m.m_klammers.describe(2); std::string source_desc = describe_sources(m); os << "\nMachine " << "\U000133DE \U00013000\n" << label("Sources", m.m_sources.size()) << source_desc << "\n" << label("Argtypes", m.m_argtypes.m_names.size()) << argtypes_desc << "\n" << label("Targets", m.m_targets.m_names.size()) << targets_desc << "\n" << label("Klammersets", m.m_klammersets.m_symbols.size()) << klammersets_desc << "\n" << label("Option sets", m.m_option_sets.m_names.size()) << option_sets_desc << "\n" << label("Klammers", m.m_klammers.m_klammers.size()) << klammer_desc << "\n" << label("State", m.m_state.m_frames.size()) << state_desc; return os; } void modify_stream(const std::string& name) { if (name == "all") std::cout << kall; if (name == "type") std::cout << ktype; if (name == "index") std::cout << kindex; if (name == "ignored") std::cout << kignored; if (name == "replaced") std::cout << kreplaced; };