Skip to content

Give a called analyzer its own _ROOT; look up bare words (4.1.1) - #740

Merged
ddehilster merged 1 commit into
masterfrom
fix/callanalyzer-root-select
Sep 14, 2026
Merged

ddehilster merged 1 commit into
masterfrom
fix/callanalyzer-root-select

Conversation

@ddehilster

Copy link
Copy Markdown
Member

What

Two bugs reported while calling EnglishPhrases on a prose zone with callanalyzer (#739).

1. @NODES _ROOT and @PATH _ROOT matched nothing in a called analyzer. The called analyzer's tree root was the node it was given, under that node's own name (e.g. _PROSEZONE), sealed, and with siblings in the caller's tree. So:

  • @NODES _ROOT / @PATH _ROOT selected nothing, and an analyzer whose passes all use @NODES _ROOT built nothing, silently;
  • selects for deeper nodes never descended, since traversal only enters unsealed nodes;
  • traverseSelect and pathSelect walk a root's right siblings, so a pass could run on the caller's nodes next to the zone.

Fix, in lite/callana.cpp only: for the length of the call the analyzer gets a stand-in _ROOT node (unsealed, no parent or siblings, spanning the node's text) that holds the node's children; they go back under the node afterwards. This leaves the ~20 select-matching sites in pat/rec/path/multi untouched, and makes a called analyzer select and traverse exactly as on a text of its own. pnroot() in a called analyzer is now that stand-in.

2. Bare words were never looked up in lazy *full dictionaries. CG::findWordConcept returned any word found in memory, even one with no attributes. Every attribute name is a dictionary word, so bare words are common, and a called analyzer shares the caller's KB: "see", "my" and "get" came out with no part of speech. A word in memory with no attributes now gets one lazy lookup (cached, so never repeated). A dict hit is merged into the word; a kbb-only hit is linked as meaning, as findFullWord already does.

Version bumped to 4.1.1.

Tests

The call-analyzer fixture's callee now uses @NODES _ROOT and @PATH _ROOT, and its caller makes "crimson" a bare word (as an attribute name) before calling. The previous binary fails it with the reported symptom (nothing built); this build passes.

Locally on Windows: all 15 fixture steps in build-windows.yml pass, including the rule-level debugger, and parse-en-us's final.tree is byte-identical to the golden copy. parse-en-us has no *full files, so the lookup change is covered by the fulldict-hang step and the fixture; it was not tested apart from fix 1.

Help: separate PR in VisualText/visualtext-files; merge it after this ships.

🤖 Generated with Claude Code

A called analyzer's tree root was the node it was given, under that
node's name, sealed, and with siblings in the caller's tree. So
@nodes _ROOT and @path _ROOT selected nothing, selects for deeper nodes
never descended, and traverseSelect/pathSelect, which walk a root's
siblings, could run on the caller's nodes next to it. It now gets a
stand-in _ROOT node holding the node's children for the length of the
call, and they go back under the node afterwards.

CG::findWordConcept returned a word found in memory without consulting
lazily loaded *full dictionaries, even when the word had no attributes.
Every attribute name is a dictionary word, so bare words are common,
and in a called analyzer the KB is shared with the caller: "see", "my"
and "get" came out with no part of speech. A bare word is now looked up
once.

The call-analyzer fixture's callee now uses @nodes _ROOT and @path
_ROOT, and its caller leaves "crimson" bare before calling.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ddehilster
ddehilster merged commit 4a6ca6f into master Sep 14, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant