Skip to content

Extend the GALEC export and render all targets from a walkable template IR - #338

Open
micahkc wants to merge 1 commit into
CogniPilot:mainfrom
micahkc:eFMI-template
Open

Extend the GALEC export and render all targets from a walkable template IR#338
micahkc wants to merge 1 commit into
CogniPilot:mainfrom
micahkc:eFMI-template

Conversation

@micahkc

@micahkc micahkc commented Aug 11, 2026

Copy link
Copy Markdown
Member

Extends the GALEC/eFMI export with matrix algebra, computed initialization, and linear-solve support, and moves every GALEC rendering onto walking templates over a language-neutral GALEC template IR. SPEC_0034 gains GAL-027..030 and D12..D17; all changes are spec-first.

Projection features

  • Matrix algebra (GAL-027): matrix×matrix / matrix×vector / vector×matrix *, transpose, and identity lower to element-unrolled, ascending-index sum trees. Chained products (A*P*transpose(A)) take true product elements (a subscript-distribution bug was found and regression-pinned). Integer array literals widen to Real.
  • initial equationStartup (GAL-028): oriented, dependency-sorted statements after literal start mirroring, with 'previous(x)' pre-slot re-seeding. The manifest start is the projection-time evaluation at default parameters (const-eval learned identity and elementwise array arithmetic), so GAL-020 mirroring holds by construction. Blanket ET021 is retired; un-lowerable forms fail with stable unsupported-feature: ids.
  • Linear solve + signals (GAL-029 slice 2a): Modelica.Math.Matrices.solve maps by name to the solveLinearEquations builtin (D13; inv/solve2 get guidance diagnostics). Method signals clauses are declared by construction via the validator's own escape-set dataflow (new rumoca_ir_galec::computed_method_escapes), the AC manifest carries per-method Signals + ErrorSignalStatus, and signal-bearing blocks switch the C ABI to status-word-returning methods with a partial-pivot LU helper. NAN relational accounting (T9) stays staged as slice 2b.
  • D12: auto-discretization (inline integration) is recorded as permanently out of scope — clocked discrete-time Modelica is the supported input.

Rendering architecture (D16/D17)

  • New template_ir.rs serializes the validated block into a walkable tree: both name spellings (GALEC quoted tokens + collision-checked identifier stems), 1-based subscripts, T7-strict Real literal text, kind-tagged expression nodes, dual whole-array value/element forms with a copy flag. Adding a target language is adding a template.
  • .alg renders from the embedded alg.jinja walking template, byte-identical to the rumoca-ir-galec typed printer (pinned by a parity test; the printer remains the parser-facing half of the language module — the parity pin is the drift guard, please don't "clean up" either side without it).
  • The C track's model.h.jinja/model.c.jinja are walking templates owning every C spelling; c_print.rs is deleted. c_mangle.rs survives solely as the Production Code manifest's name policy, kept in lockstep with the C template's keyword list by a keyword-fixture test (double/union/register variables).
  • New non-eFMI embedded-rust-galec target: a dependency-free #![no_std] crate root with Result<(), Signals> methods, honestly labeled NOT an eFMI Production Code container (the Beta-1 ProductionCode XSD restricts language to C/C++).

Fixture and tests

A quadrotor altitude-estimator fixture (examples/models/) exercises the whole scope through all four targets. Its end-to-end test is hermetic via an MSL name stub (the solve mapping is by name, so the body never inlines) and proves the C and Rust exports agree bit-for-bit with each other and to 1e-9 with an independently written reference implementation. Also new: the embedded-rust-galec suite, the estimator-scope battery (initialization/solve + the .alg parity pin), and the keyword-lockstep test.

Reviewer notes

  • Capability-gate UX change: the GALEC targets now declare initialization = true and external_functions = true, delegating rejection to the projection's precise ET002 check (with the Modelica.Math.Matrices namespace exempted since it maps by name). Same outcomes for unsupported models, different message/timing.
  • Known sharp edges (documented): Rust exports of transcendental-using models reference libm:: (models without them have zero dependencies); matrix unrolling grows with state dimension (fine at embedded scale, no guardrail for large n); the fixed-start skip matches the DAE phase's origin-string prefix (a structured origin would be sturdier — follow-up).
  • Shared-crate footprint is additive: one generic render_template_with_json_context in rumoca-phase-codegen, re-export growth, and new CLI dispatch arms. No non-GALEC code path executes a changed line.

All crate and CLI test suites pass locally (template-target render checks, the C↔Rust equivalence harness, the production-container suite, and a full workspace sweep); clippy and fmt clean; based on current main.

…te IR

SPEC_0034 gains GAL-027..030 and D12..D17. Auto-discretization is
permanently out of scope (D12): clocked discrete-time Modelica is the
supported input.

Projection features:
- Matrix algebra lowering (GAL-027): matrix x matrix / matrix x vector /
  vector x matrix products, transpose, identity element-unroll into
  ascending-index sum trees; chained products (A*P*transpose(A)) take
  true product elements; Integer array literals widen to Real.
- initial equation -> Startup lowering (GAL-028/D14): oriented,
  dependency-sorted statements after literal mirroring with pre-slot
  re-seeding; the manifest start mirrors the projection-time evaluation
  at default parameters (const-eval learned identity and elementwise
  array arithmetic); blanket ET021 retired.
- Matrices.solve -> solveLinearEquations by name (GAL-029 slice 2a/D13;
  inv and solve2 get guidance diagnostics): method signals clauses are
  declared by construction via the validator's own escape dataflow
  (rumoca_ir_galec::computed_method_escapes), the manifest carries
  per-method Signals + ErrorSignalStatus, and the C track switches to a
  status-word ABI with a partial-pivot LU helper. NAN relational
  accounting stays staged as slice 2b.

Template-IR rendering architecture (D16/D17):
- template_ir.rs serializes the validated block into a language-neutral
  walkable tree: GALEC-faithful quoted names plus identifier stems,
  1-based subscripts, T7-strict Real literal text, kind-tagged
  expression nodes, dual whole-array value/element forms with a copy
  flag. Adding a target language is adding a template.
- The .alg text renders from the embedded alg.jinja walking template,
  pinned byte-identical to the rumoca-ir-galec typed printer (parity
  test); the printer remains the parser-facing half of the language
  module.
- The C track's model.h.jinja/model.c.jinja are walking templates
  owning every C spelling; c_print.rs is deleted. c_mangle.rs survives
  as the Production Code manifest's name policy, kept in lockstep with
  the C template's keyword list by a keyword-fixture test.
- New non-eFMI embedded-rust-galec target: a dependency-free #![no_std]
  crate root with Result<(), Signals> methods (Rust is outside the
  Beta-1 ProductionCode schema, so the honesty header says so).

A quadrotor altitude-estimator fixture exercises the whole scope across
all four targets; its end-to-end test is hermetic via an MSL name stub
and proves the C and Rust exports agree bit-for-bit with each other and
to 1e-9 with an independently written reference implementation. GALEC
target capability gates now admit initialization and delegate
external-function rejection to the projection's precise ET002 check.

Signed-off-by: micahkc <mkcondie01@gmail.com>
@micahkc micahkc changed the title Extend GALEC export to Kalman-class estimators; render everything from a walkable template IR Extend the GALEC export and render all targets from a walkable template IR Aug 11, 2026
@micahkc
micahkc marked this pull request as ready for review August 11, 2026 03:56
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