feat(dsl): movement modifiers on the existing runtime actions (p8-s3) - #111
Merged
Conversation
`drive()` plus modifiers is the idiomatic DSL scenario — the standard's own style guide says so (§9.1.8) — and until now the generic actions lowered to nothing because there was nothing to shape them with. Now the modifiers are what give them content. Every §8.9 modifier lands on an IR action P2/P5 already implements, or is reported: speed targets absolute and relative, placements and gaps, lane targets and offsets. Nothing modifier-shaped is added to the runtime, which is the same rule ADR-0031 applied to composition. §8.9.1.1.1's `at` anchor decides *how*. Absent, `all` and `start` set the value when the phase begins — a Step. `end` reaches it over the phase, which is what makes p8-s2's durations load-bearing: without a concrete duration there is no interval to spread the change over, and lowering reports rather than inventing one. `position` is the modifier where the anchor changes the kind of action, not just its shape: a TeleportAction placement at the start, a LongitudinalDistanceAction gap over the phase. `keep_speed()` and `keep_position()` lower to no action at all. The runtime already holds speed and relative position between actions, so one that set the current value would be a no-op that still occupies the action domain (§7.5) and could supersede a running action. `keep_lane()` does produce one, because holding a lane is active work. `acceleration`, `along`, `along_trajectory` and `distance` are reported with their reasons and moved to Post in the coverage matrix: there is no acceleration-target action in the IR, a concrete route or trajectory can only come from §8.12.2's map methods (which the standard says may be external, §7.3.7.4), and a distance-bounded phase is not something time-based sequencing expresses. Files #110 rather than absorbing it: §7.3.3 says an overloaded enum literal resolves by "the type requirements of the place it is used in", but Scena reports the ambiguity first — so the specification's own `at: start` is rejected while `at: at!start` works. It blocks nothing and predates this sprint. 1392 gtest (+14), 194 pytest, ADR-0032.
7 tasks
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.
drive()plus modifiers is the idiomatic DSL scenario — the standard's ownstyle guide says so (§9.1.8) — and until now the generic actions lowered to
nothing because there was nothing to shape them with. The modifiers are what
give them content.
Every modifier lands on an action the runtime already has
No modifier machinery is added to the runtime; each one becomes an IR action
P2/P5 already implements, or is reported. Same rule ADR-0031 applied to
composition, and it is what keeps one runtime under two frontends.
speed(absolute)SpeedActionspeed(faster_than/slower_than/same_as,factor)SpeedActionwith aRelativeTargetSpeedchange_speedSpeedActionrelative to the actor's own speedpositionat the startTeleportActionto aRelativeObjectPositionpositionover the phaseLongitudinalDistanceActionlateralLateralDistanceActionwithside_of, elseLaneOffsetActionlaneLaneChangeAction, absolute or relativechange_laneLaneChangeActionrelative to the actorkeep_laneLaneOffsetActionat zeroThe
atanchor decides how, and needs the phase's length§8.9.1.1.1's anchor is optional. Absent,
allandstartset the value whenthe phase begins — a Step.
endreaches it over the phase, so it becomes atransition spread across the phase's length.
That is what makes p8-s2's durations load-bearing: without a concrete duration
there is no interval to spread the change over. Lowering reports and sets the
value at once rather than fabricating one, for the same reason ADR-0030 refuses
to invent performance limits.
positionis the modifier where the anchor changes the kind of action, notjust its shape — a placement at the start, a gap to reach and hold over the
phase. Both readings are in §8.9.2; the anchor chooses.
"Keep doing what you are doing" lowers to nothing
keep_speed(§8.9.6) andkeep_position(§8.9.3) constrain the actor not tochange, and the runtime already holds speed and relative position between
actions. So the faithful lowering is no action: one that set the current value
would be a no-op that still appears in the trace, occupies the longitudinal
action domain (§7.5) and could supersede something running.
keep_laneis different and does produce an action, because holding a lane isactive work — a continuous
LaneOffsetActionat zero is the runtime's way ofsaying it.
What is reported, with reasons (matrix rows moved to Post)
accelerationshapes an acceleration the phase is already performing, andthere is no acceleration-target action in the IR — the same reason §8.8's are
deferred.
along/along_trajectoryneed a concrete route or trajectory value.The DSL has no struct constructor (§7.2.2.6.7), so one can only come from
§8.12.2's
map.create_route(...)— and the standard itself says map methodsmay be external implementations (§7.3.7.4), which is post-v0.0.1.
distancebounds a phase by distance travelled, and ADR-0031 sequencesphases by time.
A checker gap found, filed rather than absorbed — #110
§7.3.3 says an overloaded enum literal "will depend on the type requirements of
the place it is used in". Scena reports the ambiguity before consulting them,
and
at(§8.9.19) androute_overlap_kind(§8.12) both declarestartandend— so the specification's ownat: startis rejected whileat: at!startis accepted.
It blocks nothing (the qualified spelling works, and is what the tests use) and
it predates this sprint — every overloaded literal the library has declared
since 43c has the same issue. Filed as #110 with the section, the failing
spelling and where the fix belongs, and recorded as a Gap row in the coverage
matrix.
Tests and docs
dsl_lowering_test.cpp45 → 59: each modifier's mapping, bothpositionreadings,
at: endwith and without a duration, the relative speed forms andtheir sign,
change_lanewithout a side, the two that lower to nothing, andeach reported one saying why.
frontend README.
1392 gtest (+14), 194 pytest.
Closes #46