Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions internal/exec/runtime/check_moves.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ func (e *StateExecutor) enabledMoves() []enabledMove {
}
picks = []int{pick}
}
moves = append(moves, enabledMove{Owner: e, Node: item.owner, Label: e.entryLabel(item.owner), Kind: moveEntry, Picks: picks})
owner := e.stateDecl(item.owner)
moves = append(moves, enabledMove{Owner: e, Node: owner, Label: e.entryLabel(owner), Kind: moveEntry, Picks: picks})
}
return moves
}
Expand All @@ -243,9 +244,9 @@ func (e *StateExecutor) enabledMoves() []enabledMove {
// where the unit draws an order among them.
func (e *StateExecutor) doMoves(due []*doAction, picked bool) []enabledMove {
moves := make([]enabledMove, 0, len(due))
names := e.stateNames(statesOf(due))
names := e.stateNames(e.statesOf(due))
for i, act := range due {
m := enabledMove{Owner: e, Node: act.state, Kind: moveDoStep, Label: "do " + names[i]}
m := enabledMove{Owner: e, Node: e.stateDecl(act.state), Kind: moveDoStep, Label: "do " + names[i]}
if picked {
m.Picks = []int{i}
}
Expand All @@ -254,10 +255,10 @@ func (e *StateExecutor) doMoves(due []*doAction, picked bool) []enabledMove {
return moves
}

func statesOf(acts []*doAction) []*ast.StateNode {
func (e *StateExecutor) statesOf(acts []*doAction) []*ast.StateNode {
states := make([]*ast.StateNode, len(acts))
for i, act := range acts {
states[i] = act.state
states[i] = e.stateDecl(act.state)
}
return states
}
Expand Down
4 changes: 2 additions & 2 deletions internal/exec/runtime/check_reduce.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func standing(exec *ActionExecutor, t Token) lower.Footprint {
func machineStanding(e *StateExecutor) lower.Footprint {
fp := dispatchFootprint(e)
for _, act := range e.doActions {
fp = unionFootprints(fp, doStepFootprint(e, act.state))
fp = unionFootprints(fp, doStepFootprint(e, e.stateDecl(act.state)))
}
return fp
}
Expand Down Expand Up @@ -114,7 +114,7 @@ func triggerChannel(trans *lower.Transition) (lower.Channel, bool) {
// by that behavior's, or the next one pending.
func doStepFootprint(e *StateExecutor, state ast.Node) lower.Footprint {
for _, act := range e.doActions {
if act.state != state {
if e.stateDecl(act.state) != state {
continue
}
if run := act.run; run != nil {
Expand Down
67 changes: 34 additions & 33 deletions internal/exec/runtime/check_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strings"

"github.com/Open-MBEE/OpenSysML/internal/ir/lower"
"github.com/Open-MBEE/OpenSysML/internal/ir/program"
"github.com/Open-MBEE/OpenSysML/internal/semantic/semantics"
"github.com/Open-MBEE/OpenSysML/internal/syntax/ast"
)
Expand Down Expand Up @@ -268,16 +269,16 @@ func (s *stateSpeller) machine(e *StateExecutor) {
s.out.WriteString(" exited")
}
if e.activeConfig != nil {
if e.activeConfig.simpleState != nil {
fmt.Fprintf(&s.out, " active{%s}", e.statePath(e.activeConfig.simpleState))
if e.activeConfig.simpleState != 0 {
fmt.Fprintf(&s.out, " active{%s}", e.statePath(e.simpleState()))
}
for _, region := range e.orderedActiveRegions() {
fmt.Fprintf(&s.out, " active{%s = %s}", regionKey(region), e.statePath(e.activeConfig.regionStates[region]))
fmt.Fprintf(&s.out, " active{%s = %s}", regionKey(region), e.statePath(e.regionActiveState(region)))
}
complete := make([]*ast.StateRegion, 0, len(e.activeConfig.defaultComplete))
for region, isComplete := range e.activeConfig.defaultComplete {
if isComplete {
complete = append(complete, region)
complete = append(complete, e.regionDecl(region))
}
}
sort.Slice(complete, func(i, j int) bool { return regionKey(complete[i]) < regionKey(complete[j]) })
Expand All @@ -286,13 +287,13 @@ func (s *stateSpeller) machine(e *StateExecutor) {
}
}
for _, state := range e.stateStack {
fmt.Fprintf(&s.out, " stack{%s}", e.statePath(state))
fmt.Fprintf(&s.out, " stack{%s}", e.statePath(e.stateDecl(state)))
}
s.history(e)
s.joinsArrived(e)
fmt.Fprintf(&s.out, " data{%s}", s.values(e.stateData))
for _, state := range sortedStates(e.stateAttrs) {
fmt.Fprintf(&s.out, " attrs{%s: %s}", e.statePath(state), s.values(e.stateAttrs[state]))
for _, state := range sortedStates(e, e.stateAttrs) {
fmt.Fprintf(&s.out, " attrs{%s: %s}", e.statePath(state), s.values(e.stateAttrs[e.stateID(state)]))
}
fmt.Fprintf(&s.out, " visits{%s}", strings.Join(e.stateVisits, ", "))
if e.eventQueue != nil {
Expand All @@ -302,20 +303,20 @@ func (s *stateSpeller) machine(e *StateExecutor) {
fmt.Fprintf(&s.out, " event{%s}", s.event(e, event))
}
}
for _, trans := range sortedTransitions(e.timerScheduled) {
for _, trans := range sortedTransitions(e, e.timerScheduled) {
fmt.Fprintf(&s.out, " timer{%s}", s.transition(e, trans))
}
for _, trans := range sortedTransitions(e.changeFired) {
for _, trans := range sortedTransitions(e, e.changeFired) {
fmt.Fprintf(&s.out, " latched{%s}", s.transition(e, trans))
}
for _, trans := range sortedTransitions(e.changePending) {
for _, trans := range sortedTransitions(e, e.changePending) {
fmt.Fprintf(&s.out, " pending{%s}", s.transition(e, trans))
}
for _, trans := range sortedTransitionKeys(e.changeObserved) {
fmt.Fprintf(&s.out, " observed{%s=%t}", s.transition(e, trans), e.changeObserved[trans])
for _, trans := range sortedTransitionKeys(e, e.changeObserved) {
fmt.Fprintf(&s.out, " observed{%s=%t}", s.transition(e, trans), e.changeObserved[e.transID(trans)])
}
for _, act := range e.doActions {
fmt.Fprintf(&s.out, " do{%s: %d pending", e.statePath(act.state), len(act.pending))
fmt.Fprintf(&s.out, " do{%s: %d pending", e.statePath(e.stateDecl(act.state)), len(act.pending))
if act.run != nil {
fmt.Fprintf(&s.out, ", paused{%s}", s.body(act.run.body))
}
Expand All @@ -327,11 +328,11 @@ func (s *stateSpeller) machine(e *StateExecutor) {
// history spells the last active child, and region children, of each state
// the machine remembers.
func (s *stateSpeller) history(e *StateExecutor) {
for _, state := range sortedStates(e.history) {
record := e.history[state]
fmt.Fprintf(&s.out, " history{%s = %s", e.statePath(state), s.stateName(e, record.child))
for _, region := range sortedRegions(record.regions) {
fmt.Fprintf(&s.out, ", %s = %s", regionKey(region), s.stateName(e, record.regions[region]))
for _, state := range sortedStates(e, e.history) {
record := e.history[e.stateID(state)]
fmt.Fprintf(&s.out, " history{%s = %s", e.statePath(state), s.stateName(e, e.stateDecl(record.child)))
for _, region := range sortedRegions(e, record.regions) {
fmt.Fprintf(&s.out, ", %s = %s", regionKey(region), s.stateName(e, e.stateDecl(record.regions[e.regionID(region)])))
}
s.out.WriteString("}")
}
Expand All @@ -340,14 +341,14 @@ func (s *stateSpeller) history(e *StateExecutor) {
// joinsArrived spells the incoming segments that have arrived at each join.
func (s *stateSpeller) joinsArrived(e *StateExecutor) {
for _, join := range e.graph.Pseudostates {
arrived := e.joinArrived[join]
arrived := e.joinArrived[e.pseudoID(join)]
if len(arrived) == 0 {
continue
}
fmt.Fprintf(&s.out, " arrived{%s: ", join.Name)
first := true
for _, segment := range e.joinIncoming(join) {
if !slices.Contains(arrived, segment) {
if !slices.Contains(arrived, e.transID(segment)) {
continue
}
if !first {
Expand All @@ -363,8 +364,8 @@ func (s *stateSpeller) joinsArrived(e *StateExecutor) {
s.out.WriteString("}")
}
fmt.Fprintf(&s.out, " data{%s}", s.bodyValues(e.stateData, e.stateCells))
for _, state := range sortedStates(e.stateAttrs) {
fmt.Fprintf(&s.out, " attrs{%s: %s}", e.statePath(state), s.bodyValues(e.stateAttrs[state], e.stateAttrCells[state]))
for _, state := range sortedStates(e, e.stateAttrs) {
fmt.Fprintf(&s.out, " attrs{%s: %s}", e.statePath(state), s.bodyValues(e.stateAttrs[e.stateID(state)], e.stateAttrCells[e.stateID(state)]))
}
fmt.Fprintf(&s.out, " visits{%s}", strings.Join(e.stateVisits, ", "))
if e.eventQueue != nil {
Expand All @@ -374,14 +375,14 @@ func (s *stateSpeller) joinsArrived(e *StateExecutor) {
fmt.Fprintf(&s.out, " event{%s}", s.event(e, event))
}
}
for _, trans := range sortedTransitions(e.timerScheduled) {
for _, trans := range sortedTransitions(e, e.timerScheduled) {
fmt.Fprintf(&s.out, " timer{%s}", s.transition(e, trans))
}
for _, trans := range sortedTransitions(e.changeFired) {
for _, trans := range sortedTransitions(e, e.changeFired) {
fmt.Fprintf(&s.out, " latched{%s}", s.transition(e, trans))
}
for _, act := range e.doActions {
fmt.Fprintf(&s.out, " do{%s: %d pending", e.statePath(act.state), len(act.pending))
fmt.Fprintf(&s.out, " do{%s: %d pending", e.statePath(e.stateDecl(act.state)), len(act.pending))
if act.run != nil {
fmt.Fprintf(&s.out, ", paused{%s}", s.body(act.run.body))
}
Expand All @@ -405,41 +406,41 @@ func regionKey(region *ast.StateRegion) string {
}

// sortedStates orders a map's state keys by identity, so the form is independent of map order.
func sortedStates[V any](m map[*ast.StateNode]V) []*ast.StateNode {
func sortedStates[V any](e *StateExecutor, m map[program.StateID]V) []*ast.StateNode {
states := make([]*ast.StateNode, 0, len(m))
for state := range m {
states = append(states, state)
states = append(states, e.stateDecl(state))
}
sort.Slice(states, func(i, j int) bool { return nodeKey(states[i]) < nodeKey(states[j]) })
return states
}

// sortedRegions orders a map's region keys by identity.
func sortedRegions[V any](m map[*ast.StateRegion]V) []*ast.StateRegion {
func sortedRegions[V any](e *StateExecutor, m map[program.RegionID]V) []*ast.StateRegion {
regions := make([]*ast.StateRegion, 0, len(m))
for region := range m {
regions = append(regions, region)
regions = append(regions, e.regionDecl(region))
}
sort.Slice(regions, func(i, j int) bool { return regionKey(regions[i]) < regionKey(regions[j]) })
return regions
}

// sortedTransitions orders a set's transitions by source and position.
func sortedTransitions(m map[*lower.Transition]bool) []*lower.Transition {
func sortedTransitions(e *StateExecutor, m map[program.TransID]bool) []*lower.Transition {
transitions := make([]*lower.Transition, 0, len(m))
for trans, set := range m {
if set {
transitions = append(transitions, trans)
transitions = append(transitions, e.transDecl(trans))
}
}
sort.Slice(transitions, func(i, j int) bool { return transitionKey(transitions[i]) < transitionKey(transitions[j]) })
return transitions
}

func sortedTransitionKeys(m map[*lower.Transition]bool) []*lower.Transition {
func sortedTransitionKeys(e *StateExecutor, m map[program.TransID]bool) []*lower.Transition {
transitions := make([]*lower.Transition, 0, len(m))
for trans := range m {
transitions = append(transitions, trans)
transitions = append(transitions, e.transDecl(trans))
}
sort.Slice(transitions, func(i, j int) bool { return transitionKey(transitions[i]) < transitionKey(transitions[j]) })
return transitions
Expand Down
11 changes: 4 additions & 7 deletions internal/exec/runtime/debug_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1296,11 +1296,8 @@ func activeStateNames(exec *StateExecutor) string {
func firedNames(exec *StateExecutor) []string {
out := make([]string, 0, exec.FiredCount())
for _, fired := range exec.FiredTransitions() {
source := ""
if fired.Source != nil {
source = StateVertexName(fired.Source)
}
out = append(out, source+"->"+StateVertexName(fired.Target))
_, from, to, _ := exec.FiredNodes(fired)
out = append(out, StateVertexName(from)+"->"+StateVertexName(to))
}
return out
}
Expand Down Expand Up @@ -1365,7 +1362,7 @@ func TestFiredSinceReleasesTheFiringsRead(t *testing.T) {
if got := exec.FiredSince(0); len(got) != 2 || got[0].Target != exec.FiredTransitions()[0].Target {
t.Errorf("FiredSince(0) = %v, want the two kept firings, the released one gone", got)
}
if got := exec.FiredSince(2); len(got) != 1 || StateVertexName(got[0].Target) != "working" {
if got := exec.FiredSince(2); len(got) != 1 || StateVertexName(exec.vertexDecl(got[0].Target)) != "working" {
t.Errorf("FiredSince(2) = %v, want waiting->working alone", got)
}
if got := firedNames(exec); !slices.Equal(got, []string{"waiting->working"}) || exec.FiredCount() != 3 {
Expand All @@ -1380,7 +1377,7 @@ func TestFiredSinceReleasesTheFiringsRead(t *testing.T) {
if err := exec.ProcessNextEvent(); err != nil {
t.Fatalf("ProcessNextEvent: %v", err)
}
if got := exec.FiredSince(3); len(got) != 1 || StateVertexName(got[0].Target) != "done" || exec.FiredCount() != 4 {
if got := exec.FiredSince(3); len(got) != 1 || StateVertexName(exec.vertexDecl(got[0].Target)) != "done" || exec.FiredCount() != 4 {
t.Errorf("FiredSince(3) = %v of %d, want working->done of 4", got, exec.FiredCount())
}
exec.KeepFired(false)
Expand Down
Loading
Loading