func NewSelectSendNode(sndr Role, dest Chan, typ types.Type) Node {
	return &SendNode{
		sndr:     sndr,
		dest:     dest,
		nondet:   true,
		t:        typ,
		children: []Node{},
	}
}
NewSelectSendNode makes a SendNode in a select (non-deterministic).
package sesstype  
import (
	"fmt"
	"go/types"
	"github.com/nickng/dingo-hunter/cfsmextract/utils"
	"golang.org/x/tools/go/ssa"
)
type op int
type Chan struct {
	def    *utils.Definition
	role   Role
	extern bool
}
func (ch Chan) Name() string {
	fullname := fmt.Sprintf("%s", ch.def.String())
	if ch.extern {
		return fullname + "*"
	}
	return fullname
}
func (ch Chan) Type() types.Type {
	if c, ok := ch.def.Var.Type().(*types.Chan); ok {
		return c.Elem()
	}
	panic("Not channel " + ch.def.Var.String())
}
func (ch Chan) Role() Role       { return ch.role }
func (ch Chan) Value() ssa.Value { return ch.def.Var }
type Role interface {
	Name() string
}
type role struct {
	name string
}
func (r *role) Name() string { return r.name }
const (
	NoOp op = iota
	NewChanOp
	SendOp
	RecvOp
	EndOp
)
type Node interface {
	Kind() op                
	Child(index int) Node    
	Append(child Node) Node  
	Children() []Node        
	String() string
}
type Session struct {
	Types map[Role]Node               
	Chans map[*utils.Definition]Chan  
	Roles map[string]Role             
}
func CreateSession() *Session {
	return &Session{
		Types: make(map[Role]Node),
		Chans: make(map[*utils.Definition]Chan),
		Roles: make(map[string]Role),
	}
}
func (s *Session) GetRole(name string) Role {  
	if _, found := s.Roles[name]; !found {
		s.Roles[name] = &role{name: name}
	}
	return s.Roles[name]
}
func (s *Session) MakeChan(v *utils.Definition, r Role) Chan {
	s.Chans[v] = Chan{
		def:    v,
		role:   r,
		extern: false,
	}
	return s.Chans[v]
}
func (s *Session) MakeExtChan(v *utils.Definition, r Role) Chan {
	s.Chans[v] = Chan{
		def:    v,
		role:   r,
		extern: true,
	}
	return s.Chans[v]
}
type NewChanNode struct {
	ch       Chan
	children []Node
}
func (nc *NewChanNode) Kind() op   { return NewChanOp }
func (nc *NewChanNode) Chan() Chan { return nc.ch }
func (nc *NewChanNode) Append(n Node) Node {
	nc.children = append(nc.children, n)
	return n
}
func (nc *NewChanNode) Child(i int) Node { return nc.children[i] }
func (nc *NewChanNode) Children() []Node { return nc.children }
func (nc *NewChanNode) String() string {
	return fmt.Sprintf("NewChan %s of type %s", nc.ch.Name(), nc.ch.Type().String())
}
type SendNode struct {
	sndr     Role        
	dest     Chan        
	nondet   bool        
	t        types.Type  
	children []Node
}
func (s *SendNode) Kind() op       { return SendOp }
func (s *SendNode) Sender() Role   { return s.sndr }
func (s *SendNode) To() Chan       { return s.dest }
func (s *SendNode) IsNondet() bool { return s.nondet }
func (s *SendNode) Append(n Node) Node {
	s.children = append(s.children, n)
	return n
}
func (s *SendNode) Child(i int) Node { return s.children[i] }
func (s *SendNode) Children() []Node { return s.children }
func (s *SendNode) String() string {
	var nd string
	if s.nondet {
		nd = "nondet "
	}
	return fmt.Sprintf("Send %s→ᶜʰ%s %s", s.sndr.Name(), s.dest.Name(), nd)
}
type RecvNode struct {
	orig     Chan        
	rcvr     Role        
	nondet   bool        
	t        types.Type  
	stop     bool        
	children []Node
}
func (r *RecvNode) Kind() op       { return RecvOp }
func (r *RecvNode) Receiver() Role { return r.rcvr }
func (r *RecvNode) From() Chan     { return r.orig }
func (r *RecvNode) IsNondet() bool { return r.nondet }
func (r *RecvNode) Stop() bool     { return r.stop }
func (r *RecvNode) Append(node Node) Node {
	r.children = append(r.children, node)
	return node
}
func (r *RecvNode) Child(index int) Node { return r.children[index] }
func (r *RecvNode) Children() []Node     { return r.children }
func (r *RecvNode) String() string {
	var nd string
	if r.nondet {
		nd = "nondet "
	}
	if r.t == nil {
		return fmt.Sprintf("Recv END %s←ᶜʰ%s%s", r.rcvr.Name(), r.orig.Name(), nd)
	}
	return fmt.Sprintf("Recv %s←ᶜʰ%s%s", r.rcvr.Name(), r.orig.Name(), nd)
}
type LabelNode struct {
	name     string
	children []Node
}
func (l *LabelNode) Kind() op     { return NoOp }
func (l *LabelNode) Name() string { return l.name }
func (l *LabelNode) Append(n Node) Node {
	l.children = append(l.children, n)
	return n
}
func (l *LabelNode) Child(i int) Node { return l.children[i] }
func (l *LabelNode) Children() []Node { return l.children }
func (l *LabelNode) String() string   { return fmt.Sprintf("%s", l.name) }
type GotoNode struct {
	name     string
	children []Node
}
func (g *GotoNode) Kind() op     { return NoOp }
func (g *GotoNode) Name() string { return g.name }
func (g *GotoNode) Append(n Node) Node {
	g.children = append(g.children, n)
	return n
}
func (g *GotoNode) Child(i int) Node { return g.children[i] }
func (g *GotoNode) Children() []Node { return g.children }
func (g *GotoNode) String() string   { return fmt.Sprintf("Goto %s", g.name) }
type EndNode struct {
	ch       Chan
	children []Node
}
func (e *EndNode) Kind() op   { return EndOp }
func (e *EndNode) Chan() Chan { return e.ch }
func (e *EndNode) Append(n Node) Node {
	e.children = append(e.children, n)
	return n
}
func (e *EndNode) Child(i int) Node { return e.children[i] }
func (e *EndNode) Children() []Node { return e.children }
func (e *EndNode) String() string   { return fmt.Sprintf("End %s", e.ch.Name()) }
type EmptyBodyNode struct {
	children []Node
}
func (e *EmptyBodyNode) Kind() op { return NoOp }
func (e *EmptyBodyNode) Append(node Node) Node {
	e.children = append(e.children, node)
	return node
}
func (e *EmptyBodyNode) Child(i int) Node { return e.children[i] }
func (e *EmptyBodyNode) Children() []Node { return e.children }
func (e *EmptyBodyNode) String() string   { return "(Empty)" }
func NewNewChanNode(ch Chan) Node {
	return &NewChanNode{ch: ch, children: []Node{}}
}
func NewSendNode(sndr Role, dest Chan, typ types.Type) Node {
	return &SendNode{
		sndr:     sndr,
		dest:     dest,
		nondet:   false,
		t:        typ,
		children: []Node{},
	}
}