Files
klammertext/mac/klammer_registry.cpp

201 lines
7.3 KiB
C++
Raw Normal View History

#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;
}
*/
2026-08-06 13:11:37 +02:00
void Klammer_registry::add(
const Argtype_registry& argtypes, const Target_registry& targets,
Option_set_registry& option_sets, katom_iter begin, katom_iter end, katom_list& katoms)
{
(void)K::log(3, *begin, *(end - 1));
restore_initial_type(begin, end);
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
auto [klammer_name, target_names, general_declared] = parse_name(targets, *begin);
if (is_in(Target_registry::optionset_name, target_names)) {
2026-08-06 13:11:37 +02:00
// The Machine routes an ".o" definition to the option set registry;
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
// reaching here means it did not. parse_name has already rejected
// ".o" as a member of a list, so this is the bare ".o" form.
2026-08-06 13:11:37 +02:00
throw Internal_error(
"The option set declaration \"" + klammer_name + ".o\" reached the klammer registry",
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);
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
}
// Sticky: once a definition has written ".*", the klammer carries the
// claim. A klammer with both a ".*" body and a target-specific one still
// asserts that the general body serves everything else.
if (general_declared) {
m_klammers[klammer_name].m_general_declared = true;
}
// One definition per target named. A comma-separated list is surface
// syntax: each target goes through the same registration, including the
// redefinition transition table, so a list that collides with an existing
// definition is decided per target -- one member may be silently ignored
// or rejected while the others are created.
for (const auto& target_name : target_names) {
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)
continue;
}
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);
}
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
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);
}
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
m_klammers[klammer_name].add_target_definition(
target_name, argtypes, option_sets, begin + 1, end - 1);
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
// This add's target:
Target target = targets.get(target_name, begin->m_loc);
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);
}
2026-08-06 13:11:37 +02:00
m_klammers[klammer_name].add_target_definition(
provide_name, argtypes, option_sets, 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<Katom>* 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<std::string, Klammer>& 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();
}
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
std::string Klammer_registry::describe(int margin, const std::string& search) const
{
/*
strings_t names {};
std::vector<strings_t> targets {};
strings_t locations {};
*/
std::string result;
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
std::string query = collapse_whitespace(search);
for (const auto& [name, k] : m_klammers) {
Target coverage: a klammer states the targets it serves kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
2026-08-12 17:20:23 +02:00
if (!query.empty() &&
!contains_fold(name, query) &&
!contains_fold(collapse_whitespace(k.description_text()), query)) {
continue;
}
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;
}