diff --git a/CHANGELOG.md b/CHANGELOG.md index d9e2c91..031af27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ All notable changes to CTParser will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### πŸ› Bug Fixes + +- **Trace mode (`@def name … end true`) no longer prints the parsed model twice** ([#344](https://github.com/control-toolbox/CTParser.jl/issues/344)). When the `:exa` backend is active, `def_fun` parses the definition a second time to build the ExaModels artifact; that second pass was inheriting the `log` flag and re-emitting the whole trace. It now runs with `log=false`. + ## [0.9.4-beta] - 2026-08-30 ### βœ… Compatibility diff --git a/src/onepass.jl b/src/onepass.jl index 5595744..62f3801 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -1550,7 +1550,9 @@ function def_fun(e; log=false) end if is_active_backend(:exa) - build_exa = def_exa(e; log=log) + # log=false: the :fun pass above already emitted the trace; a second one here + # would print the whole parsed model twice (#344) + build_exa = def_exa(e; log=false) code = concat(code, :($pref.build($p_ocp; build_examodel=($build_exa)))) else code = concat(code, :($pref.build($p_ocp))) diff --git a/test/test_onepass_fun.jl b/test/test_onepass_fun.jl index 901f93d..5f2519e 100644 --- a/test/test_onepass_fun.jl +++ b/test/test_onepass_fun.jl @@ -124,6 +124,33 @@ function test_onepass_fun() end true @test initial_time(o) == 0 @test final_time(o, [0, 2]) == 2 + + # trace mode prints the parsed model once, not once per active backend (#344) + was_exa = is_active_backend(:exa) + was_exa || activate_backend(:exa) + try + trace = mktemp() do path, io + redirect_stdout(io) do + CTParser.def_fun( + :(begin + tf ∈ R, variable + t ∈ [0, tf], time + x = (q, v) ∈ RΒ², state + u ∈ R, control + αΊ‹(t) == [v(t), u(t)] + ∫(u(t)^2) β†’ min + end); + log=true, + ) + end + flush(io) + read(path, String) + end + @test count("objective (Lagrange)", trace) == 1 + @test count("state: x, dim: 2", trace) == 1 + finally + was_exa || deactivate_backend(:exa) + end end # ---------------------------------------------------------------