ModelicaSpecification icon indicating copy to clipboard operation
ModelicaSpecification copied to clipboard

Modifiability in the context of record constructors

Open perost opened this issue 3 years ago • 14 comments

12.6 says:

Component declarations which do not allow a modification (such as final parameter Real) are declared as protected components in the record constructor function.

The obvious starting point to find out what this means would be 7.2 (Modifications), which doesn't say anything about it but contains some non-normative text which points to 4.7 (Balanced Models):

In a declaration of a component of a record, connector, or simple type, modifiers can be applied to any element, and these are also considered for the equation count.

Since 12.6 implies that there are actually components which can't be modified in a record I'm assuming the rule in 4.7 is a bit too permissive. But the rules for what can and can't be modified are spread far and wide and sometimes seems conflicting. E.g. 3.8.1 says constants can be modified after being given a value, while 4.4.4 has non-normative text saying that constants can usually not be changed after being given a value.

Given what I can find it seems like the only components that do not allow a modification in a record would be final or protected components, regardless of variability. Or have I missed something? In that case it would be good to mention that in 12.6 rather than giving a not very helpful example. If the rules are actually more complicated than that it would be good with a reference to those rules though.

perost avatar Apr 19 '21 11:04 perost

The next rule in 12.6 says:

Prefixes (constant, parameter, final, discrete, …) of the remaining record components are removed.

Does this mean that there are actually cases where final components can be modified in records? Seems odd to list final in the list of prefixes which are removed otherwise.

perost avatar Apr 19 '21 11:04 perost

Does this mean that there are actually cases where final components can be modified in records? Seems odd to list final in the list of prefixes which are removed otherwise.

I think this was just an oversight when it was added in Modelica 2.0; and I can see no discussion explaining why from that time (I cannot find the minutes from meeting 28 and 29 either which doesn't help).

HansOlsson avatar Apr 26 '21 19:04 HansOlsson

Given what I can find it seems like the only components that do not allow a modification in a record would be final or protected components, regardless of variability. Or have I missed something?

It's even simpler: A record may only contain public components https://specification.modelica.org/maint/3.5/class-predefined-types-and-declarations.html#specialized-classes (a record constructor may contain protected components but that is a function - not a record); so the only components that don't allow modification seems to be the final ones, regardless of variability.

HansOlsson avatar Apr 27 '21 12:04 HansOlsson

Given what I can find it seems like the only components that do not allow a modification in a record would be final or protected components, regardless of variability. Or have I missed something?

It's even simpler: A record may only contain public components https://specification.modelica.org/maint/3.5/class-predefined-types-and-declarations.html#specialized-classes (a record constructor may contain protected components but that is a function - not a record); so the only components that don't allow modification seems to be the final ones, regardless of variability.

Both Dymola and OpenModelica seems to think that constants with bindings are not allowed to be modified either though, but I can't find any rules in the specification that says that's the case. I.e. both fail on a model like this:

model M
  record R
    constant Integer n = 1;
  end R;

  R r = R(2);
end M;

perost avatar Apr 27 '21 12:04 perost

Both Dymola and OpenModelica seems to think that constants with bindings are not allowed to be modified either though, but I can't find any rules in the specification that says that's the case. I.e. both fail on a model like this:

Yes, 12.6 (https://specification.modelica.org/maint/3.5/functions.html#record-constructor-functions) is even explicitly listing constant as one of the things you remove when a record constructor function is derived from the record member declarations, so this should be a valid model.

henrikt-ma avatar Apr 27 '21 12:04 henrikt-ma

Both Dymola and OpenModelica seems to think that constants with bindings are not allowed to be modified either though, but I can't find any rules in the specification that says that's the case. I.e. both fail on a model like this:

Yes, 12.6 (https://specification.modelica.org/maint/3.5/functions.html#record-constructor-functions) is even explicitly listing constant as one of the things you remove when a record constructor function is derived from the record member declarations, so this should be a valid model.

That rule only applies to components that are allowed to be modified though, i.e. those that become the input parameters of the constructor. If constants with bindings are in fact not allowed to be modified it's the rule before that one that applies, i.e. they just become protected in the constructor.

perost avatar Apr 27 '21 12:04 perost

Given what I can find it seems like the only components that do not allow a modification in a record would be final or protected components, regardless of variability. Or have I missed something?

It's even simpler: A record may only contain public components https://specification.modelica.org/maint/3.5/class-predefined-types-and-declarations.html#specialized-classes (a record constructor may contain protected components but that is a function - not a record); so the only components that don't allow modification seems to be the final ones, regardless of variability.

Both Dymola and OpenModelica seems to think that constants with bindings are not allowed to be modified either though, but I can't find any rules in the specification that says that's the case. I.e. both fail on a model like this:

The likely cause for both this and the unclarity of constant in this section is that the definition of constant have changed back forth and bit, and this section was likely not updated for that.

I don't know how much that has been used in practice, if used one possibility would be to standarize current tool behavior just to avoid breaking things; and don't rely on the implicit "changeable".

HansOlsson avatar Apr 28 '21 11:04 HansOlsson

I don't know how much that has been used in practice, if used one possibility would be to standarize current tool behavior just to avoid breaking things; and don't rely on the implicit "changeable".

I tried removing the check for constants with bindings in OpenModelica and only check for final, and at least the MSL worked fine. I can make a wider test on all the libraries we test, but that'll take more time.

perost avatar Apr 28 '21 12:04 perost

Proposals to improve:

Component declarations which do not allow a modification (such as final parameter Real) are declared as protected components in the record constructor function.

One of:

  • Component declarations that are final or constant are declared as protected components in the record constructor function.
  • Component declarations that are final (and thus do not allow a modification) are declared as protected components in the record constructor function. Either is clearer than what we currently have. The first correspond to existing implementations.

I tried to see if there are any records with constants in MSL:

They exist in particular for Modelica.Electrical.Batteries.ParameterRecords and it seems that the current implementations not having the constants in the record constructors is the intent for these.

Similarly Modelica.Electrical.Spice3.Internal.ModelcardBJT2 and Modelica.Electrical.Spice3.Internal.ModelcardMOS use constant for things that shouldn't be changed.

Since the record constructor calls normally use named arguments allowing modifications will not break existing models, but it will break the intent of the models (of hiding constants).

HansOlsson avatar Apr 30 '21 11:04 HansOlsson

Note: Seems that both variants would work with existing use in MSL (the constants are not set in the calls).

HansOlsson avatar Jun 15 '21 14:06 HansOlsson

Note: Seems that both variants would work with existing use in MSL (the constants are not set in the calls).

However, I believe that the intent is that users don't change the constants in the constructor-calls. Clearly they could have been set as final to clarify that.

HansOlsson avatar Jun 23 '21 13:06 HansOlsson

I believe it's simplest to poll for this change.

The two options are (just select the smiley to choose an emoji).

  • 🚀 (rocket) Component declarations that are final or constant are declared as protected components in the record constructor function.
  • 👀 (eyes) Component declarations that are final (and thus do not allow a modification) are declared as protected components in the record constructor function.

Running the poll until end of July so that everyone has time to vote.

HansOlsson avatar Jun 23 '21 13:06 HansOlsson

To count as informative, I think a poll like this needs to be announced on the email list – I'm afraid there are generally too many GitHub notifications for most people to actually pay attention to their content.

henrikt-ma avatar Jun 24 '21 08:06 henrikt-ma

To count as informative, I think a poll like this needs to be announced on the email list – I'm afraid there are generally too many GitHub notifications for most people to actually pay attention to their content.

Even if that would be ideal, I see that the result of the poll was clear, i.e.: "Component declarations that are final (and thus do not allow a modification) are declared as protected components in the record constructor function."

HansOlsson avatar Dec 08 '21 09:12 HansOlsson