Ensure single point of responsibility in generating names and artefacts in the main program
The main program will get additions from many places in the PLC code generator. All these additions should be able to co-exist with each other in order to get a working PLC program. To ensure that, a single point in the application should be responsible for it. All PLC code generators adding to the main program should use that single point for their additions. Currently, this is already not the case (as noted in !573 (merged) ):
- The
PlcCodeStorage
generator adds hard-coded names for variables. They are not checked for uniqueness by the name generator. - An
ExprGenerator
may introduce new local variables for temporary storage in generated statements. If different instances of that generator are used for creating different parts of the main program, we could get the same name for different variables. Note that currently, temporary variables "invented" by anExprGenerator
are never stored. As such the current generator is broken (and covered by aTODO
about this point). To fix, having exactly one expression generator for the main program is much preferred.
A reasonable solution could be to make the PlcCodeStorage
responsible for the above. The hard-coded names should be offered to the name generator first to make them unique with respect to other names in their scope. Also, it should have its own expression generator, lending it to other parts of the PLC generator to create additions to the main program.
Doing that however introduces a cycle in the generator dependencies. The VariableStorage
generator uses the PlcCodeStorage
generator, and the latter needs the former to construct an ExprGenerator
instance. Setting up the generators thus will thus need at least two steps.
Some ways out:
-
An alternative is to move the expression generator of the main program to the target instance or the
VariableStorage
generator. That would solve the cycle at the cost of being illogical in structure. -
Another path is to let the target create the
Exprgenerator
for the main program, but it hands the instance over toPlcCodeStorage
afterwards. That makes the graph cyclic but it's hidden. -
A third alternative is to allow cycles in the generator graph. Instead of the current light-weight approach of passing "previous" generator instances into the constructor of a successor generator, split it in several explicit steps: a. Create all generators. They can perform basic setup themselves but not access or refer to other generators. b. Setup all links between the generators. Generators may not use the links, but should make themselves prepared for accepting calls from them. c. Tell each generator the graph has been constructed and can be used.
Obviously, this is more involved than the previous solutions. On the other hand it is also more future-resistant. It is not unreasonably to assume we may get more cycles in the graph imho.
I think the cleanest way out is the 3rd option. What do you think?
Addresses #397 (closed)
EDIT: Added a link to the overview issue