feat(plc): analyse graphical logic (FBD/LD) from PLCopen XML [#165] #169

Merged
sharang merged 1 commits from feat/plc-graphical-languages into main 2026-07-16 11:43:50 +00:00
Owner

Advances #165 (part of the CODESYS-on-Yocto tracker #167).

CODESYS control logic is frequently written in graphical languages (LD/FBD),
but the scanner only understood Structured-Text bodies — FBD/LD/SFC were skipped,
so their comm calls, hardcoded arguments and safety writes went unseen.

Approach

Reuse the existing "reconstruct synthetic ST → ST parser → rules" pipeline:

  • Blocks → calls TypeName(pin := arg, …) (fires comm/credential/port rules).
  • Out-variables / coils → assignments (fires credential / safety-bypass rules).
  • Input pins resolved by tracing connectionPointIn/refLocalId through the
    network; LD contacts AND-chain back to the power rail; nested blocks are
    referenced by a synthetic result so each call is emitted exactly once.
  • SFC graph is skipped, but ST/FBD/LD bodies embedded in its actions/transitions
    are still translated.

Also fixes

A latent doubling bug in collect_text: roxmltree descendants() yields both
an element and its child text node, so every value was collected twice. Harmless
for ST (duplicate statements deduped) but it corrupted graphical single-token
expressions (502502502, FALSEFALSEFALSE). Now only text nodes are gathered.

Tests

  • pump_fbd.xml demo fixture (Modbus block + hardcoded password + safety write).
  • fbd_graphical_body_is_analysed, ld_coil_and_block_translate_and_are_analysed,
    graphical_expression_text_is_not_duplicated.
  • Full core+agent lib suites green; fmt + clippy (agent) clean.

Follow-ons (not in this PR)

🤖 Generated with Claude Code

Advances **#165** (part of the CODESYS-on-Yocto tracker **#167**). CODESYS control logic is frequently written in **graphical languages** (LD/FBD), but the scanner only understood Structured-Text bodies — FBD/LD/SFC were skipped, so their comm calls, hardcoded arguments and safety writes went unseen. ## Approach Reuse the existing "reconstruct synthetic ST → ST parser → rules" pipeline: - **Blocks** → calls `TypeName(pin := arg, …)` (fires comm/credential/port rules). - **Out-variables / coils** → assignments (fires credential / safety-bypass rules). - **Input pins** resolved by tracing `connectionPointIn`/`refLocalId` through the network; LD contacts AND-chain back to the power rail; nested blocks are referenced by a synthetic result so each call is emitted exactly once. - **SFC** graph is skipped, but ST/FBD/LD bodies embedded in its actions/transitions are still translated. ## Also fixes A latent **doubling bug** in `collect_text`: roxmltree `descendants()` yields both an element and its child text node, so every value was collected twice. Harmless for ST (duplicate statements deduped) but it corrupted graphical single-token expressions (`502`→`502502`, `FALSE`→`FALSEFALSE`). Now only text nodes are gathered. ## Tests - `pump_fbd.xml` demo fixture (Modbus block + hardcoded password + safety write). - `fbd_graphical_body_is_analysed`, `ld_coil_and_block_translate_and_are_analysed`, `graphical_expression_text_is_not_duplicated`. - Full core+agent lib suites green; fmt + clippy (agent) clean. ## Follow-ons (not in this PR) - Native `.project` / `.projectarchive` parsing + control-app library SBOM → #165 / #166 (need a real CODESYS sample to ground). - SFC step/transition graph semantics. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
sharang added 1 commit 2026-07-16 11:36:52 +00:00
feat(plc): analyse graphical logic (FBD/LD) from PLCopen XML
CI / Deploy Agent (pull_request) Has been skipped
CI / Check (pull_request) Successful in 6m40s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
aab22d6492
CODESYS control logic is frequently written in graphical languages, but the
scanner only understood Structured-Text bodies — FBD/LD/SFC were skipped, so
their comm calls, hardcoded arguments and safety writes went unseen.

Translate FBD/LD networks to synthetic ST and run them through the existing ST
parser + rules: blocks become calls (`TypeName(pin := arg, …)`), out-variables
and coils become assignments, and input pins are resolved by tracing
`connectionPointIn`/`refLocalId` back through the network (contacts AND-chain to
the power rail; nested blocks are referenced by a synthetic result so calls are
emitted exactly once). SFC step/transition graphs are skipped, but the ST/FBD/LD
bodies embedded in their actions/transitions are still translated.

Also fixes a latent doubling bug in `collect_text`: `descendants()` yields both
an element and its child text node, so every value was collected twice. Harmless
for ST (duplicate statements landed on one synthetic line and deduped) but it
corrupted graphical single-token expressions (`502` -> `502502`,
`FALSE` -> `FALSEFALSE`). Now only text nodes are gathered.

Adds an FBD demo fixture (pump_fbd.xml) + FBD/LD/regression tests.

Part of #165 (graphical languages). Native `.project`/`.projectarchive` parsing
and SFC graph semantics remain follow-ons. Tracker #167.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sharang merged commit 386d8457d6 into main 2026-07-16 11:43:50 +00:00
sharang deleted branch feat/plc-graphical-languages 2026-07-16 11:43:50 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sharang/compliance-scanner-agent#169