Skip to content

fix(transpiler): resolve polymorphic TO_<TYPE> conversions to concrete call names#945

Open
AnayGarodia wants to merge 6 commits into
Autonomy-Logic:developmentfrom
AnayGarodia:fix/to-int-polymorphic-conversion-944
Open

fix(transpiler): resolve polymorphic TO_<TYPE> conversions to concrete call names#945
AnayGarodia wants to merge 6 commits into
Autonomy-Logic:developmentfrom
AnayGarodia:fix/to-int-polymorphic-conversion-944

Conversation

@AnayGarodia

@AnayGarodia AnayGarodia commented Jul 19, 2026

Copy link
Copy Markdown

Pull request info

References

This PR resolves #944.

Link to Jira task

N/A — this is a community GitHub issue.

Description of the changes proposed

Graphical TO_<TYPE> blocks were emitted verbatim as Structured Text calls. For example, a REAL input wired into TO_INT produced TO_INT(O_R), even though the standard catalog and both supported compilers use the concrete REAL_TO_INT(O_R) form.

This change centralizes the supported conversion targets and resolves a single-input conversion call to <SOURCE>_TO_<DESTINATION> when the input is a declared base-type local or global variable and the concrete function exists in the standard block catalog. The variable-type index is threaded through both LD and FBD emission. Unknown, unconnected, multi-input, derived-type, and block-output cases retain the previous shorthand instead of guessing a source type.

The regression suite covers the issue's exact REAL-to-INT case, local/global shadowing, sibling conversions, unknown TO_FOO targets, another block as the upstream source, derived variables, unconnected and unknown inputs, unsupported source types, non-conversion functions, and defensive multi-input handling.

Verification completed on the rebased branch:

  • 12 focused tests pass across the LD walker, graphical POU emitter, and block-library resolver.
  • The complete Jest run executed 5,234 tests: 5,231 passed and 3 were skipped. Jest then reported the repository's pre-existing global 100% coverage thresholds as unmet; this PR's changed branches are directly covered.
  • Prettier passes for the full transpiler directory. ESLint reports no errors in changed source files (only three pre-existing redundant-union warnings in block-library.ts; test files are ignored by the repository lint configuration).

🤖 Generated with Claude Code and updated after review with OpenAI Codex.

DOD checklist

  • The code is complete and according to developers’ standards.
  • I have performed a self-review of my code.
  • Meet the acceptance criteria.
  • Unit tests are written and green.
  • Test coverage: every new behavior and requested fallback branch has a regression test; the unrelated repository-wide threshold remains below 100%.
  • Integration tests are written and green. (N/A — this is isolated transpiler output logic.)
  • Changes were communicated and updated in the ticket description.
  • Reviewed and accepted by the Product Owner.
  • End-to-end test are successful. (No GUI/compiler E2E environment was available; emitted ST is validated at the transpiler boundary.)

Summary by CodeRabbit

  • New Features
    • Added polymorphic support for TO_<TYPE> conversion blocks by emitting specific conversion calls when the wired source type can be determined.
    • Improved type resolution so project-level global variable types are considered earlier.
  • Bug Fixes
    • Preserved shorthand conversion names when the source type is unknown, inputs are unconnected, upstream wiring is missing/invalid, or no supported conversion exists.
    • Avoided rewriting in unsafe scenarios (e.g., non-conversion calls with similar names, multi-input blocks, derived-type conversion sources).
  • Tests
    • Expanded end-to-end and helper-level regression coverage for local/global/derived and conversion resolution edge cases.

Copilot AI review requested due to automatic review settings July 19, 2026 20:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The ST transpiler now resolves supported TO_<TYPE> blocks to source-specific conversion calls when source types are known. Graphical POU type context includes project globals, while unresolved or unsafe cases retain shorthand calls.

Changes

Polymorphic conversion emission

Layer / File(s) Summary
Centralize conversion resolution
src/backend/shared/transpilers/st-transpiler/helpers/block-library.ts, src/backend/shared/transpilers/st-transpiler/helpers/__tests__/block-library.test.ts
Validates conversion targets and supported source/destination pairs, including temporal, BCD, identity, and boolean rules.
Propagate declared variable types
src/backend/shared/transpilers/st-transpiler/emit/pou-graphical.ts
Adds project global variables to graphical POU type resolution before local variables.
Resolve conversion calls in LD emission
src/backend/shared/transpilers/st-transpiler/walker/ld.ts, src/backend/shared/transpilers/st-transpiler/walker/__tests__/ld.test.ts
Rewrites eligible single-input blocks to concrete conversion names and preserves shorthand names for unresolved or unsafe cases.
Validate graphical conversion output
src/backend/shared/transpilers/st-transpiler/emit/__tests__/pou-graphical.test.ts
Tests local, global, shadowed, and derived source variables plus emitted conversion and temporary types.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GraphicalPou as generateGraphicalPou
  participant LdWalker as emitLdBody
  participant Resolver as resolveConversionFunctionName
  GraphicalPou->>LdWalker: emit conversion block
  LdWalker->>Resolver: resolve TO_<TYPE> from source type
  Resolver-->>LdWalker: concrete conversion name or null
  LdWalker-->>GraphicalPou: emit ST call
Loading

Possibly related PRs

Poem

I’m a rabbit, quick and bright,
TO_INT now hops just right.
REAL goes in, INT comes out,
Globals help the types sort out.
Unknown trails stay as they came—
Neat little calls, without a shame!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately describes the main transpiler change.
Description check ✅ Passed The description covers references, the fix summary, verification, and a mostly complete DOD checklist.
Linked Issues check ✅ Passed The change resolves #944 by emitting concrete conversion calls like REAL_TO_INT for supported source types.
Out of Scope Changes check ✅ Passed All changed files support conversion-name resolution or its tests; no unrelated scope is evident.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/backend/shared/transpilers/st-transpiler/walker/__tests__/ld.test.ts`:
- Around line 83-221: Add coverage for the uncovered branches: in
src/backend/shared/transpilers/st-transpiler/walker/__tests__/ld.test.ts#L83-L221,
add a conversion case whose sole input is wired to another block’s output to
exercise resolveConversionCallName upstream/variableName fallbacks; in
src/backend/shared/transpilers/st-transpiler/helpers/block-library.ts#L103-L125,
add a test for an unknown shorthand such as TO_FOO covering
resolveConversionFunctionName’s target-membership guard; in
src/backend/shared/transpilers/st-transpiler/emit/pou-graphical.ts#L146-L166,
add a derived/non-base-type interface or global variable case covering the false
branch in buildVariableTypeIndex.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d68c012a-e5a0-4930-b5bc-ca45bc90ae37

📥 Commits

Reviewing files that changed from the base of the PR and between db08561 and dcaaa82.

📒 Files selected for processing (6)
  • src/backend/shared/transpilers/st-transpiler/emit/__tests__/pou-graphical.test.ts
  • src/backend/shared/transpilers/st-transpiler/emit/pou-graphical.ts
  • src/backend/shared/transpilers/st-transpiler/helpers/block-library.ts
  • src/backend/shared/transpilers/st-transpiler/walker/__tests__/ld.test.ts
  • src/backend/shared/transpilers/st-transpiler/walker/fbd.ts
  • src/backend/shared/transpilers/st-transpiler/walker/ld.ts

AnayGarodia and others added 2 commits July 21, 2026 02:31
…e call names (Autonomy-Logic#944)

Blocks like TO_INT/TO_UINT/TO_REAL are placed on the FBD/LD canvas with
the generic IEC 61131-3 conversion shorthand as their type name, but
that shorthand is not itself a valid ST function -- only the fully
qualified <SRC>_TO_<DST> family exists (std_block_catalog.json never
has a bare TO_INT entry). The JSON->ST walker emitted the shorthand
verbatim as the call name, producing e.g. `TO_INT(O_R)` for a REAL
source, which matiec/strucpp reject as an undefined function -- the
exact "';' missing at the end of statement" parse error reported in
Autonomy-Logic#944 for `TO_INT(O_R)`.

PR Autonomy-Logic#854 already fixed the sibling defect where the synthesized output
temp's *declared type* stayed ANY for these blocks, but explicitly left
the call-name resolution as future work ("computeConnectionTypes port").
This closes that specific gap: emitFunctionCall (walker/ld.ts) now
resolves the block's single wired input to its declared type (from a
new project/POU variable-type index built in pou-graphical.ts) and
substitutes the concrete <SRC>_TO_<DST> name when the catalog has a
matching entry, falling back to the original shorthand otherwise so an
unresolvable case still surfaces the same "undefined function" error
instead of a different wrong one.

Scope: this fixes the in-process JSON->ST transpiler
(backend/shared/transpilers/st-transpiler/), which is currently opt-in
via OPENPLC_USE_NEW_TRANSPILER and is the path PR Autonomy-Logic#854 already targeted.
The default legacy pipeline (XmlGenerator -> external xml2st subprocess)
has the identical defect inherited from the original Python generator
(xml2st's own PLCGenerator.py also passes the block's raw type name
through unresolved) and needs a separate fix -- old-editor/fbd-xml.ts
has no project-wide variable-type context available at its call site
today, so resolving it there needs its own plumbing change. Flagging
that as follow-up scope rather than bundling a larger, untested change
into this fix.

Verification:
- New tests reproduce the exact issue Autonomy-Logic#944 scenario (REAL O_R ->
  TO_INT -> INT output) at both the walker level (ld.test.ts) and the
  full generateGraphicalPou level (pou-graphical.test.ts); each fails
  against the pre-fix code (bare TO_INT(O_R)) and passes with the fix
  (REAL_TO_INT(O_R)) -- confirmed by running both ways.
- Added coverage for: unconnected input, unknown source type, no
  matching catalog entry, non-conversion blocks (ADD-style), sibling
  conversions (TO_DINT from BOOL), multi-input blocks, and global
  vs. local variable shadowing.
- Full suite: 243 suites / 5216 tests, 0 failures, 0 regressions.
- tsc --noEmit and eslint clean on all changed files.

Could not run the Electron GUI or the external matiec/strucpp
compilers in this environment to compile-verify the generated ST
end-to-end; verification is at the transpiler-output level (the
generated ST text matches the exact fully-qualified call the catalog
and STruC++'s own test suite confirm is valid, e.g. REAL_TO_INT).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@AnayGarodia
AnayGarodia force-pushed the fix/to-int-polymorphic-conversion-944 branch from dcaaa82 to 8d2868b Compare July 21, 2026 09:37
…olymorphic-conversion-944

# Conflicts:
#	src/backend/shared/transpilers/st-transpiler/emit/pou-graphical.ts
#	src/backend/shared/transpilers/st-transpiler/walker/fbd.ts
#	src/backend/shared/transpilers/st-transpiler/walker/ld.ts
@AnayGarodia

Copy link
Copy Markdown
Author

Merged current development into the branch and resolved the transpiler conflicts against the new connection-type inference architecture in 492a37c. Conversion call resolution now consumes inferred pin types, while project globals remain available with POU-local shadowing. Focused regression result: 3 suites, 15 tests passed; Prettier passes; ESLint reports no errors in the changed source (only the three existing redundant-union warnings in block-library.ts).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/backend/shared/transpilers/st-transpiler/helpers/block-library.ts (1)

43-75: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Satisfy the mandatory 100% coverage gate for new shared code.

This PR adds branch-heavy code here, as well as in pou-graphical.ts and ld.ts, while the reported repository-wide Jest coverage thresholds remain unmet. Add coverage for malformed variants, global/local shadowing, conversion-pair exits, and LD fallback paths before merging.

As per coding guidelines, src/backend/shared/ must maintain 100% test coverage when new code is added.

Also applies to: 106-162

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/backend/shared/transpilers/st-transpiler/helpers/block-library.ts` around
lines 43 - 75, Add tests covering the new shared transpiler branches, including
malformed variants and variable records in blockInfosFromVariant, global/local
shadowing, conversion-pair exits, and LD fallback paths in the related
pou-graphical.ts and ld.ts logic. Ensure every newly added branch in
src/backend/shared reaches 100% coverage while preserving existing behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/backend/shared/transpilers/st-transpiler/helpers/block-library.ts`:
- Around line 43-75: Add tests covering the new shared transpiler branches,
including malformed variants and variable records in blockInfosFromVariant,
global/local shadowing, conversion-pair exits, and LD fallback paths in the
related pou-graphical.ts and ld.ts logic. Ensure every newly added branch in
src/backend/shared reaches 100% coverage while preserving existing behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9b5eaa64-45b0-4241-8b65-986d232fad7b

📥 Commits

Reviewing files that changed from the base of the PR and between 8d2868b and 492a37c.

📒 Files selected for processing (6)
  • src/backend/shared/transpilers/st-transpiler/emit/__tests__/pou-graphical.test.ts
  • src/backend/shared/transpilers/st-transpiler/emit/pou-graphical.ts
  • src/backend/shared/transpilers/st-transpiler/helpers/__tests__/block-library.test.ts
  • src/backend/shared/transpilers/st-transpiler/helpers/block-library.ts
  • src/backend/shared/transpilers/st-transpiler/walker/__tests__/ld.test.ts
  • src/backend/shared/transpilers/st-transpiler/walker/ld.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/backend/shared/transpilers/st-transpiler/helpers/tests/block-library.test.ts
  • src/backend/shared/transpilers/st-transpiler/emit/tests/pou-graphical.test.ts
  • src/backend/shared/transpilers/st-transpiler/walker/tests/ld.test.ts

@AnayGarodia

Copy link
Copy Markdown
Author

Added the requested edge-case coverage in 9202033: malformed block variants/variable records, legacy inout, local-over-global shadowing, conversion-family exits (BCD, identity, boolean, temporal, DATE_AND_TIME), and a missing-upstream LD fallback. The three focused suites now pass 20/20 tests, with block-library.ts at 100% statements/functions/lines (98.33% branches). I also ran the complete Jest suite: 260 suites and 5,382 tests passed. The command still exits nonzero on the repository-wide 100% coverage thresholds because many unchanged shared/frontend/adapter files are currently below those configured thresholds; there were no test failures.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/backend/shared/transpilers/st-transpiler/helpers/__tests__/block-library.test.ts`:
- Around line 3-47: Add tests for the uncovered valid default and
function-variant branches in blockInfosFromVariant, including variants that omit
optional fields and use the function variant type. Assert the normalized output
and rerun coverage until block-library.ts reaches 100% branch coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b7a2fa3e-68db-4781-8d74-ddb4b0ecbd04

📥 Commits

Reviewing files that changed from the base of the PR and between 492a37c and 9202033.

📒 Files selected for processing (3)
  • src/backend/shared/transpilers/st-transpiler/emit/__tests__/pou-graphical.test.ts
  • src/backend/shared/transpilers/st-transpiler/helpers/__tests__/block-library.test.ts
  • src/backend/shared/transpilers/st-transpiler/walker/__tests__/ld.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/backend/shared/transpilers/st-transpiler/walker/tests/ld.test.ts

@AnayGarodia

Copy link
Copy Markdown
Author

synced the branch with latest development, no conflicts. transpiler + backend tests all pass

1 similar comment
@AnayGarodia

Copy link
Copy Markdown
Author

synced the branch with latest development, no conflicts. transpiler + backend tests all pass

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.

Type Conversion TO_INT not working

2 participants