fix(runtime): explore every order of unordered statements in calc, constraint and case bodies - #864
Merged
Merged
Conversation
…on bodies Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ields Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ers in extents A namespace-owned binding connector (lowered via lower.NamespaceBindings) makes its ends denote the same value(s): two valueless usages share one object classified by both usages' types, a valueless end bound to a feature chain denotes the chain's object, valued ends are consistency- checked with ErrBindingConflict, and non-1..1 multiplicities refuse with the typed ErrBindingEnd semantics nested bindings use. The extent walk (only the walk) also reads and collects the values of action, state, connection, interface, allocation and flow usages — perform and exhibit included — through extentHeldFeature, while extentHeldMember keeps library-declared performances from making their holder a candidate. A namespace-level collection usage denotes its subsetters' objects first and anonymous members only to make up its lower bound; an abstract usage contributes none of its own, and under- or over-counts refuse with a typed ErrMultiplicityViolation naming the usage. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… model index The once-per-model namespace usage index (namespaceModelIndex) walks every document's namespace scopes a single time, producing each usage's subsetting usages and the namespace-owned bindings' equivalence classes — union-find over their resolved end usages — so a binding written in another package and several bindings on one usage both count. A class's value is the one a valued member declares or a chain end evaluates to (several, pairwise equal or BindingConflictError naming the two ends that differ), or one object materialized for the earliest-declared member and classified by every member's types, recorded for each member so the result and the recorded state are identical whichever member is read first; a chain end reading a member of its own class is CyclicBindingError, and the multiplicity refusal stays per binding. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…on bodies A step typed by an action, or an action a body performs, runs in an executor of its own outside the graph BodyDivides reads, so its start shot and assignment ran as one move and explore/check missed the lost update. Under one-move schedules a callee's start shot is now a boundary, its bodies divide where two moves touch shared state, and its flow pauses after each such move. An if's guard is evaluated before its branch (IfThenPerformance), so a dividing body yields between them. Statement nodes resolve their footprints in their own frame's graph. Co-Authored-By: jason.han <hanhuijun@gmail.com>
A constraint or requirement body's statements are steps of one Boolean performance, run in declaration order before its conditions are evaluated in the frame they left: locals live in a fresh frame per check, parameters are copied into it, and each condition is judged on its own Required. Writes reaching outside the performance (ErrConstraintExternalAssignment, SysML v2 §7.17.9), chained or qualified targets, send, perform and terminate (ErrConstraintEffect), stated successions (ErrStatementNotExecutable) and steps-only bodies (ErrNoConditions) are refused. The solver refuses to translate bodies stating steps. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…t and moves Co-Authored-By: jason.han <hanhuijun@gmail.com>
…onstraints The unvalued-declaration marking introduced for constraint bodies changed calc bodies' behavior (an unvalued 'attribute x;' now answers missing rather than null, breaking assignments to it and changing result errors); restrict it to the constraint host so calc/action/state bodies bind null as before. Adds the order-dependent constraint trace case, a subject-reading requirement and a specialized-def usage to the conformance case, and assume/negation subtests to the robustness suite. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…d SysML Co-Authored-By: jason.han <hanhuijun@gmail.com>
…red when dividing its flow Co-Authored-By: jason.han <hanhuijun@gmail.com>
…flow Each write to an output lands at the invoking node's pin and goes on along its streaming flows as it is made, so a performance beside the callee may observe it between two writes. Only the callee's attributes and in parameters are its own. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… and recorded occurrences, refresh the namespace index on RegisterScope, and let nested bodies read outer step locals Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ording its value Co-Authored-By: jason.han <hanhuijun@gmail.com>
…behaviors and take the largest member lower bound Co-Authored-By: jason.han <hanhuijun@gmail.com>
…n rebuilding it from objects Co-Authored-By: jason.han <hanhuijun@gmail.com>
…eclared-value seam as from an expression read Co-Authored-By: jason.han <hanhuijun@gmail.com>
…lueless scalar bindings undetermined Co-Authored-By: jason.han <hanhuijun@gmail.com>
…denotes Co-Authored-By: jason.han <hanhuijun@gmail.com>
…orders Direct body statements with no succession between them are unordered subactions, so explore, the model checker, replay and seeded runs now choose among those that may run next (a statement-order choice point), reducing orders that only swap independent statements; declared and reverse keep declaration order. A terminate action usage's body takes successions, and its implicit terminate is ordered against the body. A loop or if node of a do body's stated flow yields after each iteration and branch statement. Fixtures that meant an order state it with then. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…h that node Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
… usage again Co-Authored-By: jason.han <hanhuijun@gmail.com>
…dy-statements Co-Authored-By: jason.han <hanhuijun@gmail.com>
…o fix/atomic-body-statement-order
… into fix/atomic-body-statement-order
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
…ent-order Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/pilot-differential-baseline.json
…o fix/atomic-body-statement-order
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…nary reason to its firing Co-Authored-By: jason.han <hanhuijun@gmail.com>
…atement-order Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/pilot-differential-baseline.json
This was referenced Oct 5, 2026
Merged
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.
Depends on #840 and #829 and must merge after both. Both are merged into this branch, so until they land the diff against
developalso shows their commits; the changes of this PR are the two commitsfix(runtime): explore every order of a calc or constraint body's unordered statementsandfix(lower): leave the steps of a case stating no succession unorderedplus the merge resolutions, the self-model's scheduler choice-kind count (now thirteen, for the new guard-order choice) and the pilot baseline's re-recorded examples digest.What and why
A calc body ran its statements in declaration order inside one step, and
explore/-engine checkreported that single answer as proved. Forthe library admits
12and30, butexploresaidr = 12,proved over schedules: 1 linearization, and check saidno violation, exhaustive. Constraint bodies (#829), guards evaluating them, and analysis/verification case steps with no succession hid orders the same way.thenrelates are unordered among themselves.explore,-engine check, replay and seeded schedules reach every order; the body stays atomic (no other performance runs between its statements) and the result expression / condition is evaluated after them. Independence reuses fix(runtime): explore the order of a body's statements no succession orders #840's footprints (lower/statement_order.goCalcBodyStatementOrder,ConstraintBodyStatementOrder), so commuting statements add no choice. Nestedif/while/forand action-usage blocks inside calcs are covered.thenbetween two of a constraint body's own statements now orders them instead of being refused.runtime/order_analysis.goreordersTransitively), is onestatement orderchoice point between the distinct results its orders produce (runtime/invocation_statement_order.go), memoized per arguments within the outermost such invocation. A recursive order-dependent calc therefore explores its two outcomes in two runs instead of one choice per level.runtime/guard_statement_order.go). Inside a nested preview an order-dependent verdict, and a guard whose constraint body may write outside its performance, fail with a typed not-covered error. A check property is violated when any order violates it.statement ordersbound by check and as incomplete by explore, never as proved or exhaustive.runkeeps compiled speed.declaredandreverse(the default) run calc and constraint bodies and unordered case steps in declaration order, as they do nested action bodies, so default results do not move. (Reversing case steps would have moved an existing Monte Carlo test, so they keep declaration order.)`first` statement) instead of a Go type name.Existing fixtures whose bodies meant an order got an explicit
then:calc_iterative_factorial,calc_output_assigned_in_body,calc_block_flow_node_unvalued_pin,calc_collection_ops_in_while_loop,calc_rk4_lunar_descent,constraint_body_steps,constraint_body_steps_order. No existing expectation or trace golden changed.Not in this PR:
-constraint,-requirementand-validatestill evaluate once under the default schedule when-schedule exploreis given (they label the resultobserved).Specification basis
SysML v2 7.19/7.20: a calculation body is an action body, and⚠️ Approximate: the fixed schedules use declaration order, a tool-defined linearization), the constraint-body row, and the case-steps row (✅ → ⚠️ for the same reason).
Actions.sysmlmakesassignments,ifSubactionsandloopssubactions, which no succession orders.Cases.sysmlmakes case steps subactions likewise. Rows moved indocs/project/spec-compliance.md: a new calc/constraint unordered-statement row (How it was verified
calc_explore_statement_order({12, 30}; default12; trace goldens under default,declared,seed-1),_commuting,_declared,_derived,_recursive,_recursive_deep,_then,_then_unordered;constraint_explore_statement_order;action_guard_statement_order;state_transition_guard_statement_order;analysis_explore_step_order(+ traces,_declared),verification_explore_step_order(+_declared),analysis_case_step_order_commuting,analysis_case_step_order_stated.TestRuntimeRobustnessAtomicBodyOrder(budget exhaustion reports incomplete under explore and a bound under check, construct-named refusal, SMTnot covered, deep recursion ends in a typed budget error, impure guard refused, enclosing-binding calls not memoized) and the case-step robustness test.lowerunit tests for calc/constraint/case orders; parser goldencalc_statement_succession; SMTatomic_body_order_test.go.go build ./...,go vet ./...,gofmt -l .(empty),make lint,make docs-check,python3 scripts/changelog.py check,go test ./internal/exec/... ./internal/ir/... ./internal/check/... ./internal/translate/... ./internal/frontend/repl/... ./tests/...,go test -race ./internal/exec/runtime/.TestExecutionConformance$|TestCheckConformance, against develop + fix(runtime): explore the order of a body's statements no succession orders #840 + feat(runtime): execute constraint-body steps and complete model-determined extents #829 without this PR): no existing case's outcome or run count changed across 128 counter-bearing cases; the new fixtures run in 2–3 runs each.Checklist
make testandmake lintpass locally (make lintand the package suites above pass; fullmake testis left to CI)changes/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 changelogLink to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/27169e4b94084c969cd9f23e601f6d11
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/27169e4b94084c969cd9f23e601f6d11?variant=devin
Requested by: @HuiJun