[major] Make the shared vocabulary drive C# emission, not just check it - #222
Merged
Merged
Conversation
`QuantityVocabulary` has resolved the metadata into the quantities and operators it describes since #219, and refused the relationships whose exponents contradict their declared result. The C++ projection emitted from that resolution. The C# generator did not: it built its own type and operator lists by walking `dimensions.json` a second time, and called the vocabulary only to report SEM008 against operators it then emitted anyway. So `QuantitiesGenerator` now emits from `vocabulary.Types` and `vocabulary.Relationships`. One physics model, literally: which classes exist, what each one is and how it is bounded, and which operators relate them, all decided once and read by both targets. Two things stay on this side, and both are the language rather than the physics. A relationship becomes four C# operators — as declared, commuted, and the two divisions that undo it — because a caller who writes `duration * velocity` is not making a different claim; that expansion is `CollectOperators`. And an overload's `relationships` are C# expressions written in the metadata and pasted through, so there is nothing in them for a shared model to hold. **Breaking.** Sixteen operators and three methods are gone, being the five refused relationships in each direction C# spelled them: Sensitivity * Pressure -> VoltageMagnitude TorqueMagnitude * Angle -> Energy MomentOfInertia * AngularSpeed -> AngularMomentumMagnitude MomentOfInertia * AngularAccelerationMagnitude -> TorqueMagnitude Force{2,3,4}D.Dot(Displacement{2,3,4}D) -> Energy That is the whole of the generated diff: 105 deletions across 13 files and not one line added. `docs/migration-guide-5.0.md` says what to write instead of each, and why the fix is a physics call rather than a spelling one in all five cases. SEM008 still reports them and now says no operator is generated; `UnkeepableRelationshipTests` asserts their absence from the compiled surface by reflection, because a call that does not compile cannot be written down. Along the way: - `VocabularyIssue` carries an `IssueSite` — the names, the kind and the form — so SEM001, SEM002, SEM003 and SEM008 are all reported from the vocabulary's refusals, each with the location it had before, rather than from a second walk that reported what it dropped. - `Missing` checks each participant at the form it actually has to supply. The right operand of a product is the magnitude the vector is scaled by, so what it needs is a `vector0` however many components the relationship asks for; checking it at the declared form could name no participant at all. - The SEM003 fixtures declare real physics (`Length x Force -> Torque`). They multiplied two lengths into a length, which the vocabulary refuses for its exponents before it ever reaches the question of forms — so they would have reported SEM008 and never SEM003. They now assert which participant the message names, not merely that the name appears in it. - Both readers derive the strict-positive floor from the constraint's value rather than from the presence of the object holding it, so a constraint of another kind will not silently turn it on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGCMUrT3jBgmANHNHcPmBf
#221 fixed the Sensitivity dimension and moved the cross product to Length, which lands squarely on this branch: it was one of the five relationships whose operators this removes. The dimension said amperes per newton while the unit beside it said VoltPerPascal and the relationship agreed with the unit, so the formula was the one thing that was wrong and there was no physics call to make after all. So the removal is four relationships rather than five, and twelve operators and three methods rather than sixteen and three. Sensitivity * Pressure -> VoltageMagnitude is dimensionally true now and is generated, along with its commutation and both inverses. The migration guide says so under "what this does not change", because a reader coming from 4.3 will have seen SEM008 name it. The generated diff is again purely subtractive: 81 deletions across 10 files and not one line added. The conflicts were all the same one thing — main's text saying the four remaining refusals are still emitted, against this branch's saying the five are not — and each is resolved to the two facts that are both true: four remain, and none is emitted. The Force3D conflict was generated output either way and is regenerated. UnkeepableRelationshipTests keeps main's TheSensitivityRelationshipIsNoLongerRefused and gains, beside the dot product it asserts is gone, the cross product between the same two types asserted to still be there — so the reflective test says what was removed rather than only that something was. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGCMUrT3jBgmANHNHcPmBf
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGCMUrT3jBgmANHNHcPmBf
|
This was referenced Sep 14, 2026
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.



QuantityVocabularyhas resolveddimensions.jsoninto the quantities and operators it describes since #219, refusing the relationships whose exponents contradict their declared result. The C++ projection emitted from that resolution. The C# generator did not: it walked the metadata a second time to build its own type and operator lists, and called the vocabulary only to report SEM008 — against operators it then emitted anyway.QuantitiesGeneratornow emits fromvocabulary.Typesandvocabulary.Relationships. One physics model, literally: which classes exist, what each one is and how it is bounded, and which operators relate them, decided once and read by both targets.Two things stay on the C# side, and both are the language rather than the physics. A relationship becomes four C# operators — as declared, commuted, and the two divisions that undo it — because a caller who writes
duration * velocityis not making a different claim about physics; that expansion isCollectOperators. And an overload'srelationships(theDiameter.ToRadius()pairs) are C# expressions written in the metadata and pasted through, so there is nothing in them for a language-agnostic model to hold.Breaking change
Twelve operators and three methods are gone, being the four refused relationships in each direction C# spelled them:
TorqueMagnitude<T> * Angle<T> -> Energy<T>r × Fversusτ · θcontradictionMomentOfInertia<T> * AngularSpeed<T> -> AngularMomentumMagnitude<T>MomentOfInertia<T> * AngularAccelerationMagnitude<T> -> TorqueMagnitude<T>Force{2,3,4}D<T>.Dot(Displacement{2,3,4}D<T>) -> Energy<T>That is the whole of the generated diff: 81 deletions across 10 files and not one line added. No type was added, removed or renamed, so the storage-type alias packages are untouched.
docs/migration-guide-5.0.mdsays what to write instead of each. The first three are provably unfixable by choosing angle exponents —Torque * AngularDisplacement -> Energyforces torque's angle exponent to −1 andForce × Length -> Torqueforces it to 0 — and the fourth is fixable, by avector1form onEnergyfor a signed result to land in, which the diagnostic names rather than guesses at.The dot product is worth a second look: its exponents agree (
LMT⁻² · LisL²MT⁻², which is whatEnergyis), and the method would still have thrownArgumentExceptionon an ordinary input. A force opposing a displacement does negative work,Energydeclares only a magnitude form, andVector0Guards.EnsureNonNegativeruns on every factory. Anyone who was calling it was relying on never braking.SEM008 still reports each refusal and now says no operator is generated.
UnkeepableRelationshipTestsasserts their absence from the compiled surface by reflection — and asserts thatDisplacement3D.Cross(Force3D), which is keepable, is still there, so the test says what was removed rather than only that something was.Also in here
VocabularyIssuecarries anIssueSite— the names, the kind and the form — so SEM001, SEM002, SEM003 and SEM008 are all reported from the vocabulary's refusals, each keeping the location it pointed at before, rather than from a second walk that reported what it dropped.Missingchecks each participant at the form it actually has to supply. The right operand of a product is the magnitude the vector is scaled by, so what it needs is avector0however many components the relationship asks for; checking it at the declared form could name no participant at all.Length × Force → Torque). They multiplied two lengths into a length, which the vocabulary refuses for its exponents before it reaches the question of forms — so they would have reported SEM008 and never SEM003. They now assert which participant the message names, not merely that the name appears somewhere in it.Verification
Semantics.Test1129/1129 andSemantics.Cpp.Test27/27 pass, after the merge.mainand no new ones.Semantics.Quantities/Generated/was diffed line by line: every removal is one of the four relationships above.🤖 Generated with Claude Code
https://claude.ai/code/session_01QGCMUrT3jBgmANHNHcPmBf