From 5940917b00e64b78751ba28482722c2951f965df Mon Sep 17 00:00:00 2001 From: David de Hilster Date: Sun, 18 Oct 2026 22:26:25 -0400 Subject: [PATCH] KBFuncs: no wrapped strpiece positions, valid JSON arrays Brings this repo's KBFuncs.nlp copies in step with the canonical visualText/spec/KBFuncs.nlp fix (VisualText/visualtext-files, same branch name). The functions were replaced by one script, and only where a copy held the known old text, so every copy got the same code: - StripEndDigits: a one-letter name only came back right because position -1 wraps since engine 4.2.15, and a name with no trailing digits lost its last letter ("item" -> "ite"). It now counts positions up from 0. - SeparateConCount (where present): only the trailing digits count ("a1b2" is "a1b" + "2", not "a1" + "12"); no position arithmetic that can go negative. - JsonKBRecurse (where present): an array followed by a plain sibling is now valid JSON, adjacent arrays with different names stay separate, and the stray hier.txt debug file is gone. Shapes that were valid JSON are written byte for byte as before; matches the jsonwrite builtin fix in VisualText/nlp-engine#796. Each analyzer was run on its inputs before and after with engine 4.2.36: output unchanged. Co-Authored-By: Claude Opus 5.5 --- business/spec/KBFuncs.nlp | 11 ++++++----- files/spec/KBFuncs.nlp | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/business/spec/KBFuncs.nlp b/business/spec/KBFuncs.nlp index 8047fbd..2e73d61 100644 --- a/business/spec/KBFuncs.nlp +++ b/business/spec/KBFuncs.nlp @@ -150,13 +150,14 @@ CountName(L("con"),L("root")) { } StripEndDigits(L("name")) { + # "item12" -> "item". A name with no trailing digits comes back whole, + # an all-digit name gives 0. Positions only count up from 0, so a short + # name never reaches a negative strpiece position (which counts from the + # end since engine 4.2.15). if (strisdigit(L("name"))) return 0; - L("len") = strlength(L("name")) - 1; - L("i") = L("len") - 1; - L("str") = strpiece(L("name"),L("i"),L("len")); - while (strisdigit(L("str")) && L("i")) { + L("i") = strlength(L("name")) - 1; + while (L("i") > 0 && strisdigit(strpiece(L("name"),L("i"),L("i")))) { L("i")--; - L("str") = strpiece(L("name"),L("i"),L("len")); } return strpiece(L("name"),0,L("i")); } diff --git a/files/spec/KBFuncs.nlp b/files/spec/KBFuncs.nlp index 93cdc52..86c006f 100644 --- a/files/spec/KBFuncs.nlp +++ b/files/spec/KBFuncs.nlp @@ -117,13 +117,14 @@ CountName(L("con"),L("root")) { } StripEndDigits(L("name")) { + # "item12" -> "item". A name with no trailing digits comes back whole, + # an all-digit name gives 0. Positions only count up from 0, so a short + # name never reaches a negative strpiece position (which counts from the + # end since engine 4.2.15). if (strisdigit(L("name"))) return 0; - L("len") = strlength(L("name")) - 1; - L("i") = L("len") - 1; - L("str") = strpiece(L("name"),L("i"),L("len")); - while (strisdigit(L("str")) && L("i")) { + L("i") = strlength(L("name")) - 1; + while (L("i") > 0 && strisdigit(strpiece(L("name"),L("i"),L("i")))) { L("i")--; - L("str") = strpiece(L("name"),L("i"),L("len")); } return strpiece(L("name"),0,L("i")); }