Table of Contents

Namespace Hi.NcParsers.PostLogicSyntaxs

Classes

ModalCarrySyntax

Per-block modal-section carry. For each key in TrackedKeys, if the current block has no section for that key, deep-clone the same section from the immediately previous block (which is itself guaranteed to carry it because every block is processed by this syntax) and set AddedByKey = AddedByValue inside the cloned section. For each key in MergeKeys, a block that DID write its own (partial) section additionally receives the previous block's remaining entries — the block's own values win, only missing keys are filled — so a partially-written modal section (e.g. an XYZ-only motion block's MachineCoordinateState, which lacks the rotary axes) does not break the carry chain for the keys it did not write. Lets every block stand alone with its full modal context, so downstream readers (cache-file dumps, semantics, UI jumping to a single block) do not need EnumerateBack() to resolve modal state.

A JSON section is a candidate for TrackedKeys when ALL four criteria hold:

  1. Writers concentrated — one or two syntaxes own the section (e.g. LinearMotionSyntax / CircularMotionSyntax own MotionState; the call/return pair own SubProgramCall-derived state).
  2. Readers distributed — multiple downstream consumers each need the value, and none of them should walk back to find it. Single-reader sections do not benefit from blanket carry.
  3. Every block must see the section — cache-dump readers landing randomly, single-block UI views, and look-ahead syntaxes all require the section to be present on every block.
  4. Carry is unconditional — no frame-gating or other per-block veto. Sections that need conditional carry (e.g. FanucLocalVariableReadingSyntax's frame-aware Vars.Local dict-merge — carry only when MacroFrame matches) belong in the owning syntax's own carry logic, not here.
A section failing any criterion should be carried through its owning syntax's own logic (single-step node.Previous read, or no carry at all if absence is meaningful — e.g. MacroFrame absent = main frame).

This replaces the earlier CacheSyntax design (which sampled every Pace blocks). The legacy CacheSyntax XName is still recognised on load for backward compatibility with previously-saved project files.

RadiusCompensationSyntax

Resolves cutter radius compensation (G41/G42/G40) by offsetting the tool path perpendicular to the programmed direction.

Must be placed after motion syntaxes (CircularMotionSyntax, LinearMotionSyntax) because it reads the Hi.Motion section. Must NOT be placed inside BundleSyntax because it requires look-forward (Next).

For simple cases (line-line, no transient), the syntax overwrites MachineCoordinate with the offset position. For arc blocks that need transient bridging segments, the Motion section is replaced with a CompoundMotion containing sub-items.