#include "klammer.h" #include "klammer_registry.h" #include "show.h" #include "util.h" #include "log.h" #include "error.h" /* bool Klammer_registry::has(std::string name, std::string target) { return m_klammers.count(name) > 0; } */ void Klammer_registry::add(const Argtype_registry& argtypes, const Target_registry& targets, katom_iter begin, katom_iter end, katom_list& katoms) { (void)K::log(3, *begin, *(end - 1)); restore_initial_type(begin, end); auto [klammer_name, target_name] = parse_name(targets, *begin); if (!targets.has(target_name)) { throw Argument_error("The target \"" + target_name + "\" is not defined", begin->m_loc); } // Find the incoming definition mode katom_t incoming_deftype = katom_t::klammer_definition; for (auto it = begin + 1; it != end - 1; ++it) { if (is_deftype(it->m_type)) { incoming_deftype = it->m_type; break; } } defmode_t incoming_mode = defmode_from_katom(incoming_deftype); if (m_klammers.count(klammer_name) == 0) { m_klammers[klammer_name] = Klammer(klammer_name); } else if (m_klammers[klammer_name].m_defloc.count(target_name) > 0) { defmode_t existing_mode = m_klammers[klammer_name].m_defmode[target_name]; const auto& result = defmode_transition(existing_mode, incoming_mode); std::string name_target = klammer_name + "." + target_name; std::string at_desc = m_klammers[klammer_name].m_defloc[target_name].desc(); if (!result.replace) { if (result.message.empty()) { // Silent ignore (e.g., create + default) modify_type(katom_t::replaced, begin, end); ignore_whitespace(end, katoms); return; } std::string msg = result.message; msg = string_replace(msg, "NAME", q_(name_target)); msg = string_replace(msg, "AT", at_desc); throw Definition_error(msg, begin->m_loc); } if (result.warn) { std::string msg = result.message; msg = string_replace(msg, "NAME", q_(name_target)); msg = string_replace(msg, "AT", at_desc); warning(msg, begin->m_loc); } m_klammers[klammer_name].remove_target_definition(target_name); } m_klammers[klammer_name].add_target_definition(target_name, argtypes, begin + 1, end - 1); // This add's target: Target target = targets.get(target_name, begin->m_loc); if (!target.m_provides.empty()) { for (const auto& provide_name : target.m_provides) { if (m_klammers[klammer_name].m_defloc.count(provide_name) > 0) { m_klammers[klammer_name].remove_target_definition(provide_name); } m_klammers[klammer_name].add_target_definition(provide_name, argtypes, begin + 1, end - 1); } } modify_type(katom_t::replaced, begin, end); auto next_iter = end; if (next_iter < katoms.end()) { // std::cout << "next_iter: " << kindex << *next_iter << "\n"; } else { // std::cout << "next_iter past end. katoms length: " << katoms.size() << "\n"; } ignore_whitespace(next_iter, katoms); } void Klammer_registry::rationalize(const Target_registry& targets) { (void)K::log(3); for (auto& [name, klammer] : m_klammers) { klammer.rationalize(targets); } } /* bool Klammer_registry::has(std::string name, std::string target) { return m_klammers.count(name) > 0; } */ void Klammer_registry::check_klammer(const std::string& name, const std::string& target, const Locator& loc) const { if (m_klammers.count(name) == 0) { throw Definition_error("The klammer " + q_(name) + " is not defined for an unspecified target", loc); } const Klammer& k = m_klammers.at(name); if (k.m_defloc.count(target) == 0) { std::string desc; if (target == Target_registry::general_name) { desc = "an unspecified target"; } else { desc = "target " + q_(target); } throw Definition_error("The " + q_(name) + " klammer is not defined for " + desc, loc); } } const std::vector* Klammer_registry::constant_body(const std::string& name) const { auto it = m_klammers.find(name); if (it == m_klammers.end()) return nullptr; const Klammer& k = it->second; // A constant klammer has no parameters at all — neither in the general // definition nor inherited from a .k declaration. A "::" instance has // empty d.parameters (it inherits), so we must also check that no other // definition (especially .k) declares parameters for this klammer. for (const auto& d : k.m_defs) { if (!d.parameters.empty()) return nullptr; } for (const auto& d : k.m_defs) { if (d.target == Target_registry::general_name && d.parameters.empty()) { return &d.body; } } return nullptr; } int max_length(const std::map& ss) { size_t result = 0; for_each(ss.begin(), ss.end(), [&result](const auto& s) { result = std::max(result, s.first.size()); }); return result; } std::string Klammer_registry::instance_list(int margin) const { std::stringstream ss {}; std::string tab(margin, ' '); auto name_width = max_length(m_klammers); for (const auto& [name, k] : m_klammers) { ss << tab << std::setfill(' ') << std::setw(name_width) << name << sp_arrow << k << "\n"; } return ss.str(); } std::string Klammer_registry::describe(int margin) const { /* strings_t names {}; std::vector targets {}; strings_t locations {}; */ std::string result; for (const auto& [name, k] : m_klammers) { result += k.describe(margin) + "\n"; /* names.push_back(name); targets.push_back(k.get_target_names()); std::cout << name << " " << k.get_target_names() << "\n"; locator_summary(k.get_locations()); //locations.push_back( */ } return result; }