Date: 2026-03-19 Status: Pivoting from TypeScript/MatIEC to Rust/RuSTy
| Check | Status |
|---|---|
| Provenance | Original (Adjoint Ltd) |
| Visibility | Private |
| Language | TypeScript (pivoting to Rust) |
| Phase 1 | Complete — CLI, MCP server, PLCopen XML parser, tests, CI |
| Phase 2+ | Not started — this is where the pivot happens |
| Tag | v0.1.0-typescript-prototype preserves the TS codebase |
Phase 1 delivered a working proof-of-concept:
- MatIEC wrapper (
src/compiler/matiec.ts) — shells out toiec2cbinary, regex-parses text output into structured JSON diagnostics with LLM fix suggestions - PLCopen XML parser (
src/parsers/plcopen-xml.ts) — parses IEC 61131-10 project files into vendor-neutral types - MCP server — 5 tools:
compile_st,validate_st,plc_project_read,plc_project_create,st_reference - CLI —
plc compile,plc validate,plc parse,plc mcpwith colour output - Tests — unit tests for compiler diagnostics, XML parsing, type system
- CI — GitHub Actions: lint, test, build
This validated the concept: a headless, LLM-native PLC toolkit fills a real gap. Nobody else is building this.
The entire compiler integration (matiec.ts, 282 lines) is a wrapper that:
- Shells out to a C binary (
iec2c) - Regex-parses its unstructured text output
- Adds structured JSON and suggestions on top
This is fragile, slow, and creates a hard dependency on discovering and distributing a C binary. It cannot scale to Phase 2 (LSP, real-time diagnostics) where you need a proper parser and AST.
| Feature | MatIEC | RuSTy | Verdict |
|---|---|---|---|
| ST compilation | Yes (ST → C) | Yes (ST → LLVM native) | RuSTy — no C toolchain needed |
| Graphical languages (LD/FBD) | Yes | No | Irrelevant — our toolkit is ST-first, LLMs can't do graphical |
| Structured diagnostics | No (text output, we regex it) | plc_diagnostics module |
RuSTy — native structured errors |
| Library usage | No (shell out to binary) | Yes (Rust crate) | RuSTy — direct API |
| LLVM targets | No (needs gcc on C output) | x86, ARM, RISC-V, WASM, ESP32, AVR | RuSTy massively better |
| License | LGPL-3.0 | LGPL-3.0 | Same |
| Maturity | Battle-tested but stagnant | v0.2.0, active development | Trade-off, but RuSTy is gaining |
| WASM compilation | No | Native | Enables Phase 5 web IDE |
MatIEC gives us nothing over RuSTy for our use case.
| Factor | Detail |
|---|---|
| Consistent stack | Other Adjoint products (cross-control, digital-twin) are Rust |
| Library-first ethos | Rust crate is cleaner than npm package wrapping a C binary |
| Single binary distribution | plc compile as a static binary vs requiring Node.js 20+ |
| No host pollution | Rust binary + nix flake — no node_modules, no npm |
| WASM for web IDE | Rust compiles to WASM natively — Phase 5 gets the same engine in-browser |
| LSP ecosystem | tower-lsp is mature; many production LSPs are Rust (rust-analyzer, taplo) |
| Performance | Parsing vendor XML at scale — Rust is dramatically faster |
The vision, architecture, and plan are unchanged. The 5-phase roadmap, the competitive landscape analysis, the principles (headless-first, LLM-native, compiler-in-the-loop, vendor-neutral IR) — all still apply. What changes is the implementation language and the compiler backend.
Specifically:
PLAN.md— vision, principles, architecture diagrams, competitive landscape — all validREADME.md— the product description and MCP tool interface — still the targetexamples/— ST example files are language-agnostic- The MCP server tool interface (5 tools) — same API, different implementation
What gets replaced:
src/compiler/matiec.ts→ RuSTy crate as the compiler backendsrc/parsers/plcopen-xml.ts→ Rust XML parsing (quick-xml or roxmltree)src/cli/→ Rust CLI (clap)src/mcp-server/→ Rust MCP server (rmcp crate) or thin TS shimsrc/types/→ Rust type system- All npm/TypeScript toolchain → Cargo
- Tag preserved:
v0.1.0-typescript-prototype— the full TS codebase is accessible viagit checkout v0.1.0-typescript-prototypeforever - Clean main for Rust: remove TS source, keep docs and examples, init Cargo workspace
- Build on RuSTy: use the
rustycrate as the ST compiler backend - Reimplement Phase 1 in Rust — CLI, MCP server, PLCopen XML parser, structured diagnostics
- Proceed to Phase 2 natively — ST parser (from RuSTy's AST), LSP via
tower-lsp - MCP server — either pure Rust (rmcp) or thin TS/Python shim calling the Rust binary
- Repo: https://github.com/PLC-lang/rusty
- Crate:
plc(compiler driver),plc_ast,plc_diagnostics,plc_source - Targets: x86-64, ARM, RISC-V, WASM, ESP32, AVR
- License: LGPL-3.0
- Docs: https://plc-lang.github.io/rusty/
- RuSTy as a library vs fork? — Can we use RuSTy as a cargo dependency, or do we need to fork/vendor it for the level of integration we need?
- MCP server in Rust? — The
rmcpcrate exists but is less mature than the TS/Python MCP SDKs. May be worth a thin TS shim initially. - PLCopen XML round-trip — RuSTy doesn't do PLCopen XML. We need our own parser/serializer. This is the same work regardless of language.
- Contribution back to RuSTy — If we build vendor-neutral AST and PLCopen XML support, this could be upstreamed.