feat(fuml): translate classes, structural features, signals and active-class behavior in the referee's emitter - #413
Open
devin-ai-integration[bot] wants to merge 11 commits into
Conversation
… actions A fUML Class becomes a part def with its generals as supertypes and every attribute at its exact multiplicity; CreateObjectAction is `new T()` on the result pin and starts no behavior; Read/Add/Remove/ClearStructuralFeatureAction read or assign the object's feature as the reference implementation computes it (replacing add, first-position insert, indexed insert and remove, unique copies dropped, first or every copy removed) and hand the object on through the result pin. Untyped parameters stay untyped; an inout parameter's two nodes are told apart by their edges. The referee materializes class-typed inputs as the reference does (an object per class with defaulted features) and renders objects by type and feature, numbered by first mention, so object outputs compare. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
The referee baseline records 20 pass, 0 fail, 31 not-expressible and 4 differs-by-design: TestGeneralizationAssembly, TestClassObjectCreator, TestClassWriterReader, TestClassAttributeWriter and TestClassAttributeValueRemover move from not-expressible to pass, each adjudicated in docs/project/fuml-referee.md with its construct map row. A CreateObjectAction whose classifier is an activity is refused naming the activity rather than reported as an unknown class. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… in the referee's emitter A fUML Signal with its attributes and generalizations is an `attribute def` specializing its generals, declared before the classes and activities of the closure; a SendSignalAction is an action sending `new <Signal>(...)` to the object at its target pin with one argument pin per attribute, inherited ones included; an AcceptEventAction of one SignalEvent is an `accept` node whose result pin is the instance received. A specialized signal satisfies an accept of its general through the runtime's conformance matching. The lowering now records an accept's payload parameter as the node's output feature and the executor binds the accepted value on the accept's own performance, so an object flow out of the accept pin carries the instance on. The suite's signal activities also use an activity as a class, so their reasons sharpen and their buckets stay; the referee record and the baseline's reasons are updated, the counts unchanged. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…er-objects-and-signals
…er-objects-and-signals
…er-objects-and-signals Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # internal/exec/runtime/robustness_accept_payload_test.go # internal/exec/runtime/testdata/conformance/accept_payload_flows_from_pin.expected.json # internal/exec/runtime/testdata/conformance/accept_payload_flows_from_pin.sysml
HuiJun
marked this pull request as ready for review
September 19, 2026 22:51
…er-objects-and-signals Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # tools/referee/fuml/emit.go
…d signal attributes, lower accept triggers without a payload pin An unordered output holding objects is spelled in an order its values fix, not the order they arrived in, so equal multisets compare equal whichever object reached the parameter first. A signal attribute typed by a class is a reference to an object of that class, spelled as a class attribute is, and the class closure follows a signal's attributes so the referenced class is declared. An accept whose trigger is a condition or a time (accept when/at/after) produces no value, so it declares no output feature; only a message payload is the accept's output pin. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… removeAt on scalars A class or signal of the model named Integer, Boolean, String or Real is that classifier wherever the model references it; the primitive is then spelled ScalarValues::<name> so the package-local part def does not shadow it. A RemoveStructuralFeatureValueAction with a removeAt pin on a single-valued feature empties it at position 1 regardless of the value pin, as the reference implementation removes by position. Co-Authored-By: jason.han <hanhuijun@gmail.com>
A class's or signal's effective attributes held both an inherited property and the one redefining it, so a specialized signal with one logical attribute expected two argument pins and a redefined class attribute was declared twice. The reader keeps each property's redefinedProperty references, AllAttributes drops what another effective property redefines, and the emitter spells the redefinition as `:>>`. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
There was a problem hiding this comment.
Devin Review found 2 new potential issues.
2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)
…t includingAt validate every insertion position An external type reference (an href fragment from the UML primitive types or the fUML library) names no class or signal of the model, whatever XMI id a local classifier carries; ClassOf, SignalOf, primitive and the classifier's behavior lookup all return none for it. A positioned add hands every position but `*` to includingAt, so a position of 0 is the runtime's out-of-range error rather than an insertion first. Co-Authored-By: jason.han <hanhuijun@gmail.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.
What and why
The fUML referee's emitter (
tools/referee/fuml/emit.go) translated only the primitive-valued activities of the reference implementation's test models; nine expressible activities stayednot-expressiblewith anot yet translated:reason because they create objects, write structural features, accept signals or run a class's behavior. This PR grows the emitter over those constructs, one construct group per commit, and extends the referee so object-valued inputs and outputs execute and compare.Draft — work in progress. The status of each group:
Done: classes, object creation, structural features
Class→part def, generals as:>supertypes, each attribute at its exact declared multiplicity ([0..*] ordered nonunique,[0..3], …; the UML default[1..1]unwritten). Classes are resolved by ID first and then by name, so a type reference with a usable ID but no name resolves.CreateObjectAction→action N { out result : T = new T(); }— creation starts no behavior (that isStartObjectBehaviorAction, under active classes below).ReadStructuralFeatureAction→out result … = object.f;at the feature's multiplicity.AddStructuralFeatureValueAction/RemoveStructuralFeatureValueAction/ClearStructuralFeatureAction→assign object.f := …;with the reference implementation's semantics: a replacing add or a single-valued feature takes the value; a unique feature drops its old copy; an unpositioned add inserts first (the reference'sFirstChoiceStrategy),insertAtinserts at that position with*appending; a remove drops every copy (isRemoveDuplicates), the copy atremoveAt, or the first copy; clear empties. The original object flows on through the result pin.ReadSelfAction→thisinside a class-owned behavior; at the top level it stays a typedTranslateError("reads self in an activity no class owns").String) are declared without a type; aninoutparameter's input and output nodes are told apart by their edges.tools/referee/fuml/run.go) now materializes class-typed inputs the way the reference'sEnvironment.makeValuedoes (an object per class, features defaulted recursively) and renders object outputs by type and feature, numbered by first mention, soObject/Referencerecords compare.Done: signals
Signal→attribute defwith its attributes, specializing its generals, declared before the classes and activities of the closure.SendSignalAction→ an action sendingnew <Signal>(…)to the object at its target pin, one argument pin per attribute, inherited ones included.AcceptEventActionof oneSignalEvent→ anacceptnode whose result pin is the instance received; a specialized signal satisfies an accept of its general through the runtime's conformance matching.internal/ir/lower/action_graph.go) records an accept's payload parameter as the node's output feature and the executor (internal/exec/runtime/action_executor.go) binds the accepted value on the accept's own performance, so an object flow out of the accept pin carries the instance on. Conformance pairaccept_payload_flows_from_pinandTestRuntimeRobustnessAcceptPayloadcover it.TestSignalReceiveris a top-level activity with an attribute thatTestSpecializedSignalSendinstantiates and starts), so their reasons sharpen and their buckets stay until the active-class group lands.Merged:
develop's layering relayoutorigin/developis merged in (internal/core/runtime→internal/exec/runtime,internal/core/lower→internal/ir/lower, corpus gates →tests/corpus). Every file this PR adds or edits is at its new path; the runtime's added conformance pair and robustness test were relocated by hand. The relayout changed nothing in substance for this PR — only paths.Referee so far (
go run -C tools ./cmd/fuml-referee -jobs 8):Moved to
pass:TestGeneralizationAssembly,TestClassObjectCreator,TestClassWriterReader,TestClassAttributeWriter,TestClassAttributeValueRemover, adjudicated indocs/project/fuml-referee.md; the baseline is updated and-checkis clean. The classifier's 27 rows did not move. Four rows remain the emitter's:ActiveClassBehavior,ActiveClassBehaviorSender,TestSignalReceiver,TestSpecializedSignalSend.Remaining
StartObjectBehaviorActionstarting it asynchronously (never creation), an activity used as a class (ActiveClassBehavior,ActiveClassBehaviorSender,TestSignalReceiver,TestSpecializedSignalSend).failwith the reason.docs/project/fuml-referee.md/spec-compliance.md/ changelog pass,-update/-check,-jsondeterminism, full gates, un-draft.Specification basis
fUML 1.5 (formal/2021-07-01) § 8.6 Actions —
CreateObjectAction,ReadSelfAction, the structural feature actions,SendSignalAction,AcceptEventAction— as the pinned reference implementation (v1.5.0a) executes them; § 8.8 for the object-behavior startup still to come. Thespec-compliance.mdrow citing the fUML referee carries the counts above.How it was verified
tools/referee/fuml/emit_test.go:TestEmitClasses,TestEmitObjectCreationAndFeatureWrites,TestEmitFeatureReads,TestEmitReadSelf,TestEmitRefusesAnActivityAsObject,TestExecuteObjects,TestEmitSignals,TestEmitSignalTypedAttribute,TestEmitSendSignal,TestEmitAcceptEvent,TestExecuteSignalson hand-built models; every emitted model passesValidate.internal/exec/runtime: conformance pairtestdata/conformance/accept_payload_flows_from_pin.{sysml,expected.json},robustness_accept_payload_test.go.go build ./...,go vet ./...,gofmt -l .(empty),go test ./...(root andtools/),make lint,make docs-check,python3 scripts/changelog.py check,mkdocs build --strict— all clean after the merge.OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 go test -count=1 ./tests/corpus -run 'TestTrainingExamples|TestPilotCorpora'clean../scripts/download-fuml-suite.sh && go run -C tools ./cmd/fuml-referee -jobs 8 -checkclean;-jsontwice byte-identical; the baseline's provenance (tag, commit, digests) unchanged.Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)F4,K5) in the body, docs, or changelog