Klammerset: the @@@klammerset construct, its search path, and const correctness

The @@@klammerset system command formally declares a klammerset — a
named, logically related group of klammer definitions — with an
operative, idempotent declaration (:requires and :files load in order
at the declaration point, relative to the declaring file). A bare
symbol given to ktext -k, kdesc --input, or :requires resolves to
x/x.k on the search path: the document's directory, then
KLAMMERTEXT_KLAMMERSETS, then KLAMMERTEXT_HOME; kdesc --klammerset
lists the available sets. sks/sks.k is the first declared klammerset,
so `-k sks` loads the SKS by name. The engine's lookup classes were
renamed *_set → *_registry to keep the two concepts apart, and the
whole C++ tree now follows standard const-correctness conventions.
tst/ gains klammerset_test.sh (18 cases).

(from dev 64b1abf23e56)
This commit is contained in:
2026-07-30 23:50:07 +02:00
parent c42981f7e2
commit ef77f03584
83 changed files with 1429 additions and 594 deletions

View File

@@ -13,7 +13,7 @@ using namespace std::literals;
std::regex Klammer::name_re = std::regex(R"((\w+)(?:\.(\w+))?)");
std::tuple<std::string, std::string>
parse_name(Target_set targets, Katom name_katom)
parse_name(const Target_registry& targets, const Katom& name_katom)
{
std::string name_with_target = trim_char(name_katom.m_text, '@');
std::smatch match {};
@@ -29,7 +29,7 @@ parse_name(Target_set targets, Katom name_katom)
std::string klammer_name = match[1];
std::string target_name = match[2];
if (target_name.empty()) {
target_name = Target_set::general_name;
target_name = Target_registry::general_name;
}
if (!targets.has(target_name)) {
throw Target_error(
@@ -41,7 +41,7 @@ parse_name(Target_set targets, Katom name_katom)
}
std::tuple<Katom, Parameter_set, katom_list, Locator>
parse_definition_katoms(std::string klammer_name, Argtype_set argtypes, katom_iter& begin, katom_iter& end)
parse_definition_katoms(const std::string& klammer_name, const Argtype_registry& argtypes, katom_iter& begin, katom_iter& end)
{
(void)K::log(3, *begin, *(end - 1));
katom_iter deftype = std::find_if(
@@ -84,7 +84,7 @@ parse_definition_katoms(std::string klammer_name, Argtype_set argtypes, katom_it
}
void Klammer::add_target_definition(
std::string target_name, Argtype_set argtypes, katom_iter begin, katom_iter end)
const std::string& target_name, const Argtype_registry& argtypes, katom_iter begin, katom_iter end)
{
(void)K::log(3, *begin, *(end-1));
auto [deftype, parameters, body, loc] =
@@ -95,7 +95,7 @@ void Klammer::add_target_definition(
std::regex variable_re(R"(\*(\w+)\*)");
int i = 0;
variable_map_t varmap {};
for (auto k : body) {
for (const auto& k : body) {
std::smatch match {};
std::string txt = k.m_text;
while (std::regex_search(txt, match, variable_re) &&
@@ -127,23 +127,23 @@ void Klammer::remove_target_definition(const std::string& target_name)
// Rationalize multiple definitions
std::string error_list(std::string label, auto components, std::string after="")
std::string error_list(const std::string& label, const auto& components, const std::string& after="")
{
std::stringstream ss {};
ss << label << ":\n";
for (auto c : components) {
for (const auto& c : components) {
ss << " " << c.loc.desc() << "\n";
}
ss << after;
return ss.str();
}
auto Klammer::target_defs(std::vector<std::string> target_names)
auto Klammer::target_defs(const std::vector<std::string>& target_names)
{
std::vector<Klammer::components> defs {};
for (auto target : target_names) {
for (const auto& target : target_names) {
auto target_defs = collect_if(
m_defs, [target](const auto& def) { return def.target == target; });
m_defs, [&target](const auto& def) { return def.target == target; });
defs.insert(defs.end(), target_defs.begin(), target_defs.end());
}
return defs;
@@ -173,7 +173,7 @@ void Klammer::disallow_instances() //Klammer::components declaration)
}
}
bool Klammer::copy_to_instances(Target_set targets)
bool Klammer::copy_to_instances(const Target_registry& targets)
{
auto instances = instance_defs();
if (!instances.empty()) {
@@ -202,19 +202,20 @@ bool Klammer::copy_to_instances(Target_set targets)
}
void Klammer::copy_components(
Parameter_set parameters, std::vector<Klammer::components> cs, Target_set targets)
const Parameter_set& parameters, const std::vector<Klammer::components>& cs,
const Target_registry& targets)
{
(void)K::log(4);
for (auto target_name : targets.m_names) {
if (target_name == Target_set::declare_name ||
target_name == Target_set::general_name) {
for (const auto& target_name : targets.m_names) {
if (target_name == Target_registry::declare_name ||
target_name == Target_registry::general_name) {
continue;
}
m_parameters = parameters;
}
for (auto c : cs) {
for (const auto& c : cs) {
m_body[c.target] = c.body;
m_body_generic[c.target] = (c.target == Target_set::general_name);
m_body_generic[c.target] = (c.target == Target_registry::general_name);
m_varmap[c.target] = c.varmap;
}
}
@@ -223,7 +224,7 @@ void Klammer::copy_components(
void Klammer::check_for_multiple_general_klammers()
{
auto general_klammers = target_defs({Target_set::general_name});
auto general_klammers = target_defs({Target_registry::general_name});
if (general_klammers.size() > 1) {
throw Definition_error(
error_list(
@@ -235,11 +236,11 @@ void Klammer::check_for_multiple_general_klammers()
void Klammer::check_for_declaration_and_definitions()
{
auto declares = target_defs({Target_set::declare_name});
auto declares = target_defs({Target_registry::declare_name});
if (!declares.empty()) {
std::vector<Klammer::components> definitions {};
for (auto def : m_defs) {
if (def.target != Target_set::declare_name) {
for (const auto& def : m_defs) {
if (def.target != Target_registry::declare_name) {
if (def.deftype == katom_t::klammer_definition ||
def.deftype == katom_t::klammer_default) {
msg() << def << "\n";
@@ -261,11 +262,11 @@ void Klammer::check_for_declaration_and_definitions()
// If a general definition exists, use it for targets not defined, but check signatures
void Klammer::copy_general_klammer_to_undefined(Target_set targets)
void Klammer::copy_general_klammer_to_undefined(const Target_registry& targets)
{
(void)K::log(4);
auto general_klammers = target_defs({Target_set::general_name});
auto declares = target_defs({Target_set::declare_name});
auto general_klammers = target_defs({Target_registry::general_name});
auto declares = target_defs({Target_registry::declare_name});
// Check matching signatures (though this case already handled)
if (general_klammers.size() == 1) {
@@ -279,13 +280,13 @@ void Klammer::copy_general_klammer_to_undefined(Target_set targets)
m_parameters.m_katoms[0].m_loc, false);
}
}
auto [target, deftype, parameters, body, varmap, loc] = general_klammers[0];
const auto& [target, deftype, parameters, body, varmap, loc] = general_klammers[0];
if (m_parameters.m_katoms.empty()) {
m_parameters = parameters;
}
for (auto target_name : targets.m_names) {
for (const auto& target_name : targets.m_names) {
// std::cout << "General copy, considering " << target_name << "\n";
if (m_body.count(target_name) == 0 && target_name != Target_set::declare_name) {
if (m_body.count(target_name) == 0 && target_name != Target_registry::declare_name) {
// std::cout << " Copying to " << target_name << "\n";
m_body[target_name] = body;
m_body_generic[target_name] = true; // general body -> writer content
@@ -298,7 +299,7 @@ void Klammer::copy_general_klammer_to_undefined(Target_set targets)
// Three declaration cases: none, one, many
void Klammer::no_declarations(Target_set targets)
void Klammer::no_declarations(const Target_registry& targets)
{
(void)K::log(4);
// std::cout << boldblack << "No declarations\n" << black;
@@ -308,7 +309,7 @@ void Klammer::no_declarations(Target_set targets)
std::vector<std::string> target_names = targets.applicable();
std::vector<Parameter_set> all_parameter_sets {};
// Are all parameters the same?
for (auto def : m_defs) {
for (const auto& def : m_defs) {
if (std::ranges::find(target_names, def.target) != target_names.end()) {
// std::cout << " Found: " << def.target << "\n";
all_parameter_sets.push_back(def.parameters);
@@ -332,7 +333,7 @@ void Klammer::no_declarations(Target_set targets)
copy_general_klammer_to_undefined(targets);
}
void Klammer::one_declaration(Target_set targets, Klammer::components declare)
void Klammer::one_declaration(const Target_registry& targets, const Klammer::components& declare)
{
(void)K::log(4);
// std::cout << boldblack << "One declaration\n" << black;
@@ -342,7 +343,7 @@ void Klammer::one_declaration(Target_set targets, Klammer::components declare)
copy_general_klammer_to_undefined(targets);
}
void Klammer::many_declarations(std::vector<Klammer::components> declares)
void Klammer::many_declarations(const std::vector<Klammer::components>& declares)
{
(void)K::log(4);
// std::cout << boldblack << "Many declarations\n" << black;
@@ -353,10 +354,10 @@ void Klammer::many_declarations(std::vector<Klammer::components> declares)
void Klammer::rationalize(Target_set targets)
void Klammer::rationalize(const Target_registry& targets)
{
(void)K::log(3, m_name);
auto declares = target_defs({Target_set::declare_name});
auto declares = target_defs({Target_registry::declare_name});
auto declare_count = declares.size();
if (declare_count == 0) {
disallow_instances();
@@ -371,7 +372,7 @@ void Klammer::rationalize(Target_set targets)
}
std::string klammer_name_from_katom(std::string s, Locator loc)
std::string klammer_name_from_katom(const std::string& s, const Locator& loc)
{
std::regex rgx(R"(@(\w+).*)");
std::smatch match {};
@@ -389,11 +390,11 @@ void label(const std::string& s)
std::cout << std::right << std::setw(w) << std::setfill(' ') << s << ": ";
}
void show_args(const std::string& label_text, std::vector<Argument> arguments)
void show_args(const std::string& label_text, const std::vector<Argument>& arguments)
{
if (!arguments.empty()) {
label(label_text);
for (auto a : arguments) {
for (const auto& a : arguments) {
std::cout << a << " ";
}
std::cout << '\n';
@@ -403,7 +404,7 @@ void show_args(const std::string& label_text, std::vector<Argument> arguments)
strings_t Klammer::get_target_names() const
{
strings_t names {};
for (auto [target, body] : m_body) {
for (const auto& [target, body] : m_body) {
std::stringstream ss {};
// ss << name << target.m_loc.m_line;
ss << target;
@@ -422,12 +423,12 @@ strings_t Klammer::get_locations()
return {};
}
std::string Klammer::signature_text()
std::string Klammer::signature_text() const
{
std::string result {};
bool has_pos = false;
bool has_opt = false;
for (auto pos : m_parameters.m_positional) {
for (const auto& pos : m_parameters.m_positional) {
result += pos.m_name;
std::string type = pos.m_argtype.m_name;
if (type != default_argtype) {
@@ -442,7 +443,7 @@ std::string Klammer::signature_text()
if (opt_count <= 3 && !has_pos) {
result += " ";
}
for (auto opt : m_parameters.m_optional) {
for (const auto& opt : m_parameters.m_optional) {
if (opt_count > 3) {
result += "\n :" + opt.m_name;
} else {
@@ -473,18 +474,18 @@ std::string Klammer::signature_text()
}
std::string Klammer::description_text()
std::string Klammer::description_text() const
{
std::string result = " [" + m_name + ": no description]";
if (m_body.contains("k")) {
result = to_string(m_body["k"], true);
result = to_string(m_body.at("k"), true);
result = justify(result, 80, 1);
}
return result;
}
std::string Klammer::describe(int margin)
std::string Klammer::describe(int margin) const
{
std::string result {};
result += "@" + m_name + signature_text() + description_text();