Make @def hygienic: the generated code should contain the modules, not their names
I maintainer di solito rispondono entro 1 giorno
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Summary
The code generated by @def names the modules CTModels, ExaModels and CTBase by symbol, so it only runs in a module that has bindings with these names. Today, OptimalControl.@def does not work after a plain import OptimalControl. Put the modules themselves in the generated code instead, and remove the configurable prefixes, which no longer have a purpose.
The problem
With CTParser 0.9 and OptimalControl 2.2:
module M
import OptimalControl
ocp = OptimalControl.@def begin
t ∈ [0, 1], time
x ∈ R, state
u ∈ R, control
x(0) == 0
ẋ(t) == u(t)
∫(u(t)^2) → min
end
end
UndefVarError: `CTModels` not defined in `Main.M`
using OptimalControl works, because OptimalControl re-exports the module names CTModels, ExaModels and CTBase for this reason only (@reexport import CTModels: CTModels # for generated code (prefix)). So every user of @def depends on the namespace of OptimalControl, and using OptimalControl: @def or import OptimalControl does not work. The @Lie macro of CTLie has the same issue: control-toolbox/CTLie.jl#40.
Where the names come from
In src/onepass.jl, about twenty code generators start with pref = prefix_fun() (or prefix_exa(), or the error prefix) and generate :($pref.state!(…)). The prefixes are Ref{Symbol} (PREFIX_FUN, PREFIX_EXA, E_PREFIX), with defaults :CTModels, :ExaModels and :CTBase in src/defaults.jl, and setters prefix_fun!, prefix_exa! and e_prefix!. The symbol is resolved in the module where the user calls the macro.
The prefixes were introduced when the functions were re-exported through OptimalControl, and OptimalControl was the prefix of everything. This is no longer the case, and in the ecosystem only the tests of CTParser (test/test_prefix.jl) set them to another value.
Proposal: dependencies on the three packages, and the modules in the generated code
Make CTBase, CTModels and ExaModels direct dependencies of CTParser, and generate the code with the module values:
# before
pref = prefix_fun() # a Symbol, resolved in the caller's module
:($pref.state!(…))
# after
pref = CTModels # the module itself
:($pref.state!(…))
The generator lines are the same. A module value interpolated before a dot is resolved when the macro is defined, not in the caller's module:
julia> m = Module(:Elsewhere); pref = Base;
julia> Core.eval(m, :($pref.sin(1.0)))
0.8414709848078965
Changes:
- Add
CTModelsandExaModelsto[deps](andLinearAlgebra, a standard library), with their compat. CTModels does not depend on CTParser, so there should be no cycle. - Replace
prefix_fun(),prefix_exa()ande_prefix()by three constants, in one place (for exampleFUN = CTModels,EXA = ExaModels,ERR = CTBase). RemovePREFIX_FUN,PREFIX_EXA,E_PREFIX, their getters and setters,__default_prefix_*,__default_e_prefix, their docstrings andtest/test_prefix.jl. - Move the methods of the extension
CTParserExaModelsinto the main module, since ExaModels is no longer optional. - Document the removal of
prefix_fun!,prefix_exa!ande_prefix!in the changelog: it is a change of the public API.
Effects:
import OptimalControlandusing OptimalControl: @defwork.- The compat
ExaModels = "0.12", which the generated code already requires, is enforced. - OptimalControl no longer needs to re-export
CTModels,ExaModelsandCTBasefor the generated code (see the issue below). - ExaModels is loaded with CTParser, including for users of the functional backend only. It is a dependency of OptimalControl already.
Alternative, without new dependencies
If CTParser should not depend on CTModels and ExaModels, keep the prefixes, but let them hold a Module instead of a Symbol (Ref{Any}), and let OptimalControl set them once, in its __init__:
function __init__()
CTParser.prefix_fun!(CTModels)
CTParser.prefix_exa!(ExaModels)
end
The generated code then contains the modules, and the generators do not change. Today, this fails at the first step: CTParser.prefix_fun!(CTModels) raises Cannot convert an object of type Module to an object of type Symbol, since the Ref is typed. Drawbacks: a global state in CTParser, which depends on the loading order if CTParser is used without OptimalControl, and CTParser keeps its optional dependencies and the extension.
Test
In a fresh module, with import OptimalControl only (or import CTParser and the packages loaded), check that @def builds a problem, for the functional backend and for :exa, and in a module that defines its own CTModels binding, that the result is the same.
- Lingua principale
- Julia
- Stelle
- 3
- Fork
- 0
- Merge medio
- 1g 32m
- PR unite (30g)
- 18
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di control-toolbox/CTParser.jl
-
Generate every representation of each component; remove the discretization from the :exa backendForse già presa @jbcaillau l’ha presa 4 giorni fa. Aperta
control-toolbox/CTParser.jl#415 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Keep the :exa constraint handles by label and return the path/boundary multipliers by labelForse già presa @jbcaillau l’ha presa 7 giorni fa. Aperta
control-toolbox/CTParser.jl#414 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
[Dev] Automatic names of the components (x₁, x1, …): limit of 9 for a symbolic dimensionForse già presa @jbcaillau l’ha presa 9 giorni fa. Apertafeature
control-toolbox/CTParser.jl#403 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
[Dev] Digit exponents R²¹, R¹⁰⁰: keep the limit of 20 or read the exponent?Forse già presa @jbcaillau l’ha presa 9 giorni fa. Apertafeature
control-toolbox/CTParser.jl#402 · 1 commento · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
[Design] Should a constraint bound be allowed to depend on the model? Levels of relaxationForse già presa @jbcaillau l’ha presa 9 giorni fa. Apertadev
control-toolbox/CTParser.jl#401 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di control-toolbox/CTParser.jl
Issue simili
-
documentation priority: high
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
epiforecasts/BVDOutbreakSize#1260 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
TuringLang/Turing.jl#2917 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100