You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
CTParser (v0.8.15) turns the @def DSL into executable model-building code, through two parsing backends living side by side in onepass.jl (~1500 lines): :fun generates function-based CTModels code, :exa generates a full ExaModels transcription (variables on a grid, scheme-dependent dynamics defects, cost quadrature, constraints). The package is a flat module with generated code addressed through mutable prefix Refs. A detailed roadmap has been written, companion to the CTDirect roadmap.
Guiding principle
The parser describes the problem; it does not discretize it. Scheme-dependent code (defects, quadrature, endpoint-control fixes, grids) belongs to CTDirect.
ExaModels 0.11 migration (§1) — Compat blocker for the whole ecosystem (CTDirect and CTSolvers also pin ExaModels = "0.9"). Audit all generated ExaModels call sites, bump compat, coordinate the bump across packages.
Move the discretization out of the parser (§2, the structural item) — The :exa backend stops generating scheme-dependent transcription code. Two routes: (1) function tracing — CTDirect traces CTModels functions into ExaModels generators, CTParser needs no :exa backend at all; (2) expression IR — CTParser stores a neutral expression representation, CTDirect generates the Exa transcription from it. Joint with CTDirect §5. Absorbs issues [Dev] Add non uniform grid for exa #65 (non-uniform grid), [Dev] Constrain endpoint controls #161 (endpoint-control constraints), [Dev] Exa retrieve multipliers for boundary and path constraints #134 (exa multipliers).
"1-D = scalar" simplification (§3) — Emitted closures should work when callers pass scalars for 1-D state/control/variable. Coordinate with CTDirect §7 and CTModels.
Remove prefixes (§4, [Dev] Remove prefixes #224) — Replace mutable prefix Refs (PREFIX_FUN, PREFIX_EXA) with direct module-qualified code (CTModels.…, CTBase.…). Removes global mutable state, makes generated code readable and greppable.
Parsing engine redesign (§7) — Staged compiler-style pipeline over a typed IR: Stage 0 (surface normalization), Stage 1 (grammar → typed IR nodes), Stage 2 (semantic validation: symbol table, constraint classification, dimension resolution, strictness checks), Stage 3 (backend emission). Replaces the 1500-line monolithic onepass.jl. The IR is route 2's neutral representation — engine redesign and Exa repatriation converge on the same object. Submodule split follows the stages (IR, Grammar, Semantics, FunBackend, ExaBackend, InitialGuess, Defaults).
Test suite restructuring (§8) — Adopt the Handbook testing template, organize by functionality (grammar, strictness, codegen_fun, codegen_exa, initial_guess, integration), keep :exa tests as golden oracle for CTDirect's repatriation.
Documentation (§9) — Vitepress migration + a complete DSL grammar reference page derived from the §7 IR productions, with doctests.
Why
Separating parsing from semantics via an IR will make the DSL more maintainable and extensible:
New transformations (multi-phase, penalization, symbolic reduction) can operate at the IR level without touching the parser
Adding a production = adding one file (node struct + parse rule + validate method + emit methods) — plain open multiple dispatch
Adding a backend = adding emit methods, not duplicating the grammar
Removing the ExaModels transcription clarifies the responsibility boundary with CTDirect
Strictness rules become centralized stage-2 checks on data instead of guards scattered through codegen
Error accumulation: one @def can report all its errors with positions in one shot
Objective
Refactor CTParser following the control-toolbox Handbook philosophy to build a better base for future extensions.
Context
CTParser (v0.8.15) turns the
@defDSL into executable model-building code, through two parsing backends living side by side inonepass.jl(~1500 lines)::fungenerates function-based CTModels code,:exagenerates a full ExaModels transcription (variables on a grid, scheme-dependent dynamics defects, cost quadrature, constraints). The package is a flat module with generated code addressed through mutable prefixRefs. A detailed roadmap has been written, companion to the CTDirect roadmap.Guiding principle
The parser describes the problem; it does not discretize it. Scheme-dependent code (defects, quadrature, endpoint-control fixes, grids) belongs to CTDirect.
Key points (from the detailed roadmap)
:exabackend stops generating scheme-dependent transcription code. Two routes: (1) function tracing — CTDirect traces CTModels functions into ExaModels generators, CTParser needs no:exabackend at all; (2) expression IR — CTParser stores a neutral expression representation, CTDirect generates the Exa transcription from it. Joint with CTDirect §5. Absorbs issues [Dev] Add non uniform grid for exa #65 (non-uniform grid), [Dev] Constrain endpoint controls #161 (endpoint-control constraints), [Dev] Exa retrieve multipliers for boundary and path constraints #134 (exa multipliers).Refs (PREFIX_FUN,PREFIX_EXA) with direct module-qualified code (CTModels.…,CTBase.…). Removes global mutable state, makes generated code readable and greppable.as_rangeissues,__wrapscoping), stricter parsing withParsingErrorfor silent mis-parses ([Dev] Stricter parsing #193: leftover symbols, [Dev] Improve parsing #139: undefined time arguments), finalize slice notation ([Bug] Comprehensive Slice Notation Tests #260:x[1:3](t),x[1:end](t),x[1:n](t)).ẋ₁(t)as sugar for∂(x₁)(t), [Dev] Coordinate derivatives aliases #71), tensors/matrix-valued state and control ([Dev] Adding tensors #181, cross-package design note first), incremental@def!with$-interpolation (Incremental @def! #32).onepass.jl. The IR is route 2's neutral representation — engine redesign and Exa repatriation converge on the same object. Submodule split follows the stages (IR, Grammar, Semantics, FunBackend, ExaBackend, InitialGuess, Defaults).:exatests as golden oracle for CTDirect's repatriation.Why
Separating parsing from semantics via an IR will make the DSL more maintainable and extensible:
@defcan report all its errors with positions in one shotReferences