Support the Behavior Annex port updated value 🤖 - #3216
Merged
Conversation
AS5506/3 Rev. A lists 'updated among the D.5 port services and admits it in the D.7 value_variable production as "port_name ' updated", beside 'count and 'fresh. The BA grammar spells only the count and fresh suffixes, in both ReferenceExpression and UnindexedReferenceExpression, so 'updated is a syntax error: "no viable alternative at input 'updated'". The error is not confined to the suffix. In Issue3171.aadl the action of the second transition loses its assignment and its names are read as source states of the next transition. Issue3171.aadl writes the value on an incoming data port in an execute condition, on an incoming event data port in a condition with the value of a data-less incoming event port in the action beside it, and on a port reached through a feature group. Its three assertions pin the three things the value needs beyond parsing: - The strict model gives it a port value of its own metaclass holding the named port, with the feature group kept beside the port the way every other port holder keeps it. The metaclass is read by name so that a run without the support reports the representation it did build rather than failing to compile. The action block is collected separately from the condition, because the strict model keeps every block under the annex and has the transition refer to it rather than contain it. - The value types as a universal Boolean with no data classifier. D.5 makes it equivalent to the core Updated runtime service - true when new values were received in the port since its last freeze, without freezing it - so there is no data classifier to carry, and that is also what lets it apply to an event port that carries no data at all, the way a port fresh value already does. - The value round-trips through the registered unparser, because the generated sequencers have to emit the suffix as well as the parser having to read it. It serializes a copy: the registered unparser returns the source text of anything that still has a node model. The copy joins the parsed resource for the duration, because serializing the unit and classifier cross-references needs the scope that resource provides. Every port the model names is incoming, which is what D.5's description of the value is about. The production spells "port_name" rather than the "incoming_port_name" it uses for a plain port read, so it admits an outgoing port too, but neither the D.5 nor the D.7 legality rules say what the value would mean there, so the model takes no position on that case. All three assertions currently fail on the syntax error, which is neither the rule nor the location a user needs, and the second and third would still fail on the type and on the serialized text if only the grammar were extended. The characterization goldens record that rejection so the fix commit shows the complete change. The model project is self-contained: every diagnostic in the golden generated without the Behavior Annex validator comes from the unparsable suffix itself, so the model carries no unrelated AADL error. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AS5506/3 Rev. A lists 'updated among the D.5 port services and admits it in the D.7 value_variable production as "port_name ' updated", beside 'count and 'fresh. The grammar spelled only the count and fresh suffixes, in both ReferenceExpression and UnindexedReferenceExpression, so 'updated was a syntax error at the suffix and the rest of the transition was read as something else entirely: in Issue3171.aadl the action of the second transition lost its assignment and its names were taken for source states of the next transition. Add the suffix to both rules and a PortUpdatedValue to the strict model. It is an ActualPortHolder like PortCountValue and PortFreshValue, so the port the user named has somewhere to go and a value reached through a feature group keeps its group holder beside it, the way every other port holder does. Adding it to UnindexedReferenceExpression as well keeps the two rules' suffix sets equal; that rule stands for a property array index, where the translator drops the suffix today for count and fresh alike. The Ecore addition and the code generated from it come from the model generators. The type rules give it a universal Boolean, which is what D.5 gives it and what PortFreshValue already establishes: the data representation is Boolean and the data classifier stays null. D.5 makes the value equivalent to the core Updated runtime service - true when new values were received in the port since its last freeze, and it does not freeze the port - so there is no data classifier to carry. The null classifier is not incidental either. It is what lets the value apply to an event port that carries no data at all, because nothing then asks that port for a classifier it does not have. The translator also excludes the value where it excludes count, fresh, and dequeue: an actual parameter in a writable position becomes a Target only when it is a plain reference, and a port value is a value rather than something a subprogram can assign to. Serializer and content-assist support follow from the generated sequencers and proposal provider, so the value round-trips. No legality check comes with this. The production spells "port_name" rather than the "incoming_port_name" it uses for a plain port read, so it admits an outgoing port, and neither the D.5 nor the D.7 legality rules narrow that - even though D.5 describes all three port services only in terms of input freeze: 'updated reports values "received ... since the last freeze", 'count counts "frozen elements", and 'fresh reports a value "received ... by the previous dispatch or freeze". There is therefore no stated rule to enforce, and the existing behavior for the two older services is the same: the covering-syntax corpus reads 'count and 'fresh off an outgoing port with no diagnostic. The G07 row of the conformance document records that tension rather than resolving it, and the regression model names incoming ports only. 'updated joins 'count and 'fresh as a word the annex reserves. No model in the corpus used it as an identifier: regenerating the characterization goldens changed only the two fixtures that write the value. BehaviorAnnexConformanceTest now requires acceptance of PortUpdated.aadl instead of recording its rejection, which closes conformance finding G07. That fixture needed no correction. Fixes #3171 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3171
Cause and correction
AS5506/3 Rev. A lists
'updatedamong the D.5 port services and admits it in the D.7value_variableproduction asport_name ' updated, beside'countand'fresh. The grammar spelled only the count and fresh suffixes, in bothReferenceExpressionandUnindexedReferenceExpression, so'updatedwas a syntax error at the suffix and the rest of the transition was read as something else entirely: in the regression model the action of the second transition lost its assignment and its names were taken for source states of the next transition.UnindexedReferenceExpressionas well keeps the two rules' suffix sets equal; that rule stands for a property array index, where the translator drops the suffix today forcountandfreshalike.PortUpdatedValue, anActualPortHolderlikePortCountValueandPortFreshValue, so the port the user named has somewhere to go and a value reached through a feature group keeps its group holder beside it. The Ecore addition and the code generated from it come from the model generators.PortFreshValuealready establishes — data representation Boolean, data classifier null. D.5 makes the value equivalent to the coreUpdatedruntime service, true when new values were received in the port since its last freeze and without freezing it, so there is no data classifier to carry. The null classifier is also what lets the value apply to an event port that carries no data at all, because nothing then asks that port for a classifier it does not have.Targetonly when it is a plain reference, and a port value is a value rather than something a subprogram can assign to.BehaviorAnnexConformanceTestnow requires acceptance ofPortUpdated.aadlinstead of recording its rejection, which closes conformance finding G07. That fixture needed no correction.No legality check
The production spells
port_namerather than theincoming_port_nameit uses for a plain port read, so it admits an outgoing port, and neither the D.5 nor the D.7 legality rules narrow that — even though D.5 describes all three port services only in terms of input freeze:'updatedreports values "received … since the last freeze",'countcounts "frozen elements", and'freshreports a value "received … by the previous dispatch or freeze". There is therefore no stated rule to enforce here, and the existing behavior for the two older services is the same: the covering-syntax corpus reads'countand'freshoff an outgoing port with no diagnostic. The G07 row ofba/doc/conformance.mdrecords that tension rather than resolving it, and the regression model names incoming ports only. Deciding a house interpretation and enforcing it for all three services is tracked separately.Regression model and assertions
ba/org.osate.ba.tests/models/issue3171/Issue3171.aadlwrites the value on an incoming data port in an execute condition, on an incoming event data port in a condition with the value of a data-less incoming event port in the action beside it, and on a port reached through a feature group.Issue3171Testpins the three things the value needs beyond parsing:portUpdatedResolvesToAPortValueOfItsOwn— the strict metaclass and the port each value holds, in the order the annex writes them, with the feature group kept beside its port. The metaclass is read by name so that a run without the support reports the representation it did build rather than failing to compile. The action block is collected separately from the condition, because the strict model keeps every block under the annex and has the transition refer to it rather than contain it.portUpdatedIsAUniversalBoolean—AadlBaUtils.getTypeHolderreturns Boolean with no data classifier for all four values, including the data-less event port.portUpdatedRoundTripsThroughTheUnparser— the annex serializes with the suffix and reparses to the same strict shape. It serializes a copy, because the registered unparser returns the source text of anything that still has a node model, and the copy joins the parsed resource for the duration so that the unit and classifier cross-references have the scope they need.All three failed on
no viable alternative at input 'updated'before the fix, and the second and third would still have failed on the type and on the serialized text if only the grammar had been extended. The characterization goldens in the first commit record that rejection, so the second commit shows the complete change. Every diagnostic in the golden generated without the BA validator comes from the unparsable suffix itself, so the model carries no unrelated AADL error.'updatedjoins'countand'freshas a word the annex reserves. No model in the corpus used it as an identifier: regenerating the characterization goldens changed only the two fixtures that write the value.Validation
Focused regression, from the repository root:
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0All nine Behavior Annex bundles with their tests:
Tests run: 128, Failures: 0, Errors: 0, Skipped: 4inorg.osate.ba.testsandTests run: 15, Failures: 0, Errors: 0, Skipped: 0inorg.osate.xtext.aadl2.ba.tests.BehaviorAnnexConformanceTestreportsTests run: 12, Failures: 0, Skipped: 4; the skips are the four conformance findings still open, one fewer than before, andeveryStandardExpectationNamesItsTrackingIssueenforces thatTRACKED_SKIPSagrees.Clean root-reactor build:
BUILD SUCCESS, 3176 tests run, 0 failures, 0 errors, 8 skipped.Dependencies
None. The branch is based on
masterat 817cb70 and contains the regression commit followed by the production-fix commit.Residual risk
AadlBaPackageclassifier IDs of the enums and data types that follow it. The newgenClassesentry is appended last so the shift stays confined to those constants, but any consumer that hard-codes a classifier ID rather than using the generated constant would be affected.'updatedis now a reserved word in the annex, as'countand'freshalready are. A pre-existing model that usesupdatedas an identifier inside abehavior_specificationwould stop parsing. No model in the 100-fixture corpus does.'countand'fresh: accepted, undiagnosed, and unresolved by the standard.🤖 Generated with Claude Code