func (sys *CFSMs) chanToMachine(ch Role, T string, m *cfsm.CFSM) { q0 := m.NewState() qEnd := m.NewState() for _, machine := range sys.Roles { q1 := m.NewState() // q0 -- Recv --> q1 tr0 := cfsm.NewRecv(machine, T) tr0.SetNext(q1) q0.AddTransition(tr0) // q1 -- Send --> q0 for _, machine2 := range sys.Roles { if machine.ID != machine2.ID { tr1 := cfsm.NewSend(machine2, T) tr1.SetNext(q0) q1.AddTransition(tr1) } } // q0 -- STOP --> qEnd (same qEnd) tr2 := cfsm.NewRecv(machine, STOP) tr2.SetNext(qEnd) qEnd.AddTransition(tr2) // qEnd -- STOP --> qEnd for _, machine2 := range sys.Roles { if machine.ID != machine2.ID { tr3 := cfsm.NewSend(machine2, STOP) tr3.SetNext(qEnd) qEnd.AddTransition(tr3) } } } m.Start = q0 }
func (sys *CFSMs) nodeToMachine(role Role, node Node, q0 *cfsm.State, m *cfsm.CFSM) { switch node := node.(type) { case *SendNode: to, ok := sys.Chans[node.To()] if !ok { log.Fatal("Cannot Send to unknown channel", node.To().Name()) } tr := cfsm.NewSend(to, node.To().Type().String()) qSent := m.NewState() for _, c := range node.Children() { sys.nodeToMachine(role, c, qSent, m) } tr.SetNext(qSent) q0.AddTransition(tr) case *RecvNode: from, ok := sys.Chans[node.From()] if !ok { log.Fatal("Cannot Recv from unknown channel", node.From().Name()) } msg := node.From().Type().String() if node.Stop() { msg = STOP } tr := cfsm.NewRecv(from, msg) qRcvd := m.NewState() for _, c := range node.Children() { sys.nodeToMachine(role, c, qRcvd, m) } tr.SetNext(qRcvd) q0.AddTransition(tr) case *EndNode: ch, ok := sys.Chans[node.Chan()] if !ok { log.Fatal("Cannot Close unknown channel", node.Chan().Name()) } tr := cfsm.NewSend(ch, STOP) qEnd := m.NewState() for _, c := range node.Children() { sys.nodeToMachine(role, c, qEnd, m) } tr.SetNext(qEnd) q0.AddTransition(tr) case *NewChanNode, *EmptyBodyNode: // Skip for _, c := range node.Children() { sys.nodeToMachine(role, c, q0, m) } case *LabelNode: sys.States[m][node.Name()] = q0 for _, c := range node.Children() { sys.nodeToMachine(role, c, q0, m) } case *GotoNode: qTarget := sys.States[m][node.Name()] for _, c := range node.Children() { sys.nodeToMachine(role, c, qTarget, m) } default: log.Fatalf("Unhandled node type %T", node) } }