From 35ca469e4d22ed87c406537f2b22db60d40f8f12 Mon Sep 17 00:00:00 2001 From: Andy Kopra Date: Sun, 18 Oct 2026 23:19:37 +0200 Subject: [PATCH] Argtype descriptions name a literal parameter's cost, a phase's error is the phase's report, the ^-code table's grave-accent and dieresis rows (from dev ee86ca467512) --- README.md | 2 +- mac/argtype_registry.h | 18 ++++++++++++++++-- mac/character.h | 2 +- mac/eval.h | 9 +++++++++ mac/eval_python.cpp | 9 +++++++++ mac/machine.cpp | 29 +++++++++++++++++++++++++++-- ref/reflect.cpp | 3 +++ 7 files changed, 66 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b10a92b..8da8ce5 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ are regenerated on each release — patches cannot be merged directly. Report problems (or send patches) to the author; accepted changes are applied to the development tree and appear in a following snapshot. -This snapshot was assembled from development commit `831455f36fcd`. +This snapshot was assembled from development commit `ee86ca467512`. ## License diff --git a/mac/argtype_registry.h b/mac/argtype_registry.h index e46ac65..3af90d2 100644 --- a/mac/argtype_registry.h +++ b/mac/argtype_registry.h @@ -87,7 +87,18 @@ std::vector> diacritics { {"h", {"0302", "circumflex (hat)"}}, {"~", {"0303", "tilde"}}, {"-", {"0304", "macron"}}, - {"\"", {"0308", "diaresis"}}, + {"\"", {"0308", "dieresis"}}, // {"v", {"0305", "vinculum"}}, {"b", {"0306", "breve"}}, {"d", {"0307", "dot above"}}, diff --git a/mac/eval.h b/mac/eval.h index 87be4c6..c04c249 100644 --- a/mac/eval.h +++ b/mac/eval.h @@ -36,3 +36,12 @@ public: Machine m_machine; Locator m_loc; }; + +// The Python exception the last fetch saw (Eval_python::fetch_python_exception): +// its type name and its str(). The Error that fetch produces carries the +// whole traceback; a caller that wants the exception's OWN words for a +// headline -- Machine::run_phase_functions, reporting a phase's ValueError +// as the phase's message about the document -- reads these. Declared here +// so machine.cpp needs no Python header. (TODO 77, 2026-10-13) +std::string last_python_exception_type(); +std::string last_python_exception_text(); diff --git a/mac/eval_python.cpp b/mac/eval_python.cpp index a17f098..b666bb6 100644 --- a/mac/eval_python.cpp +++ b/mac/eval_python.cpp @@ -6,6 +6,12 @@ std::regex Eval_python::statement_delimiter("\\s*;\\s*"); PyObject* Eval_python::s_last_exception = nullptr; +// See eval.h. Set by fetch_python_exception(), beside the object it keeps. +static std::string s_last_exception_type {}; +static std::string s_last_exception_text {}; +std::string last_python_exception_type() { return s_last_exception_type; } +std::string last_python_exception_text() { return s_last_exception_text; } + static bool s_python_output_to_log = false; void set_python_output_to_log(bool on) @@ -226,6 +232,9 @@ std::string Eval_python::fetch_python_exception() detail = PyUnicode_AsUTF8(str); Py_DECREF(str); } + s_last_exception_text = detail; + s_last_exception_type = + ptype ? reinterpret_cast(ptype)->tp_name : ""; PyObject* tb_module = PyImport_ImportModule("traceback"); if (tb_module) { PyObject* format = PyObject_GetAttrString(tb_module, "format_exception"); diff --git a/mac/machine.cpp b/mac/machine.cpp index c406d27..bd7f768 100644 --- a/mac/machine.cpp +++ b/mac/machine.cpp @@ -909,7 +909,9 @@ std::string Machine::run_phase_functions() // result text. The Eval is constructed per phase so a chained // phase sees its predecessor's result in K_result. Eval E(*this, Locator()); - if (!f.empty() && f[0] != ':') { + const std::string spec = f; + const bool python_phase = !f.empty() && f[0] != ':'; + if (python_phase) { // K reaches a phase only as a parameter: the state's // "class K" exists in the EVAL's globals (python_code() // defines it), but a phase function's body resolves names in @@ -929,7 +931,30 @@ std::string Machine::run_phase_functions() // Klammertext: take the raw result string. Re-reading it as // Klammertext (Eval::eval) would misparse target characters -- // e.g. a "@" from a quoted ^@ in justified txt output. - m_result = E.eval_command(katoms.begin(), katoms.end() - 2); + try { + m_result = E.eval_command(katoms.begin(), katoms.end() - 2); + } catch (const Parsing_error& e) { + // A Python phase's exception is the phase's report about the + // document, not a parsing error at "phase, line 1": a phase + // raises ValueError to say what is wrong (phases. + // check_section_links), and that message is what the user + // needs headlined, located nowhere -- the phase ran over the + // whole target text, so no line is the place. Any other + // exception type is a fault in the phase itself and keeps + // its type name. The traceback the Parsing_error carried is + // the trace, at -v 2. (TODO 77, 2026-10-13) + if (!python_phase) throw; + (void)K::log(2, e.m_desc); + std::string what = last_python_exception_text(); + const std::string type = last_python_exception_type(); + if (what.empty()) throw; + if (type != "ValueError") what = type + ": " + what; + throw Target_error( + what + "\n\n(Reported by the " + m_state.value("K_target") + + " target's phase " + spec + + "; -v 2 shows the Python traceback.)", + Locator::none()); + } } } return m_result; diff --git a/ref/reflect.cpp b/ref/reflect.cpp index b297eaf..4e2b100 100644 --- a/ref/reflect.cpp +++ b/ref/reflect.cpp @@ -39,6 +39,9 @@ std::string diacritics_examples([[maybe_unused]] Machine& machine) if (sym == "~") { written = "^" + letter + "^~"; } + if (sym == "`") { + written = "^" + letter + "^`"; + } std::string display = "^" + letter + sym; kt << display << " | @t ^" << written << " @ | " << name << " ||\n"; }