github.com/nevalang/neva@v0.23.1-0.20240507185603-7696a9bb8dda/internal/runtime/adapter/adapter.go (about) 1 package adapter 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/nevalang/neva/internal/runtime" 8 "github.com/nevalang/neva/internal/runtime/ir" 9 ) 10 11 type Adapter struct{} 12 13 func (a Adapter) Adapt(irProg *ir.Program) (runtime.Program, error) { //nolint:funlen 14 runtimePorts := make(runtime.Ports, len(irProg.Ports)) 15 16 for _, portInfo := range irProg.Ports { 17 runtimePorts[runtime.PortAddr{ 18 Path: portInfo.PortAddr.Path, 19 Port: portInfo.PortAddr.Port, 20 Idx: uint8(portInfo.PortAddr.Idx), 21 }] = make(chan runtime.Msg, portInfo.BufSize) 22 } 23 24 runtimeConnections := make([]runtime.Connection, 0, len(irProg.Connections)) 25 for _, conn := range irProg.Connections { 26 senderPortAddr := runtime.PortAddr{ 27 Path: conn.SenderSide.Path, 28 Port: conn.SenderSide.Port, 29 Idx: uint8(conn.SenderSide.Idx), 30 } 31 32 senderPortChan, ok := runtimePorts[senderPortAddr] 33 if !ok { 34 return runtime.Program{}, fmt.Errorf("sender port not found %v", senderPortAddr) 35 } 36 37 meta := runtime.ConnectionMeta{ 38 SenderPortAddr: senderPortAddr, 39 ReceiverPortAddrs: make([]runtime.PortAddr, 0, len(conn.ReceiverSides)), 40 } 41 receiverChans := make([]chan runtime.Msg, 0, len(conn.ReceiverSides)) 42 43 for _, rcvr := range conn.ReceiverSides { 44 receiverPortAddr := runtime.PortAddr{ 45 Path: rcvr.PortAddr.Path, 46 Port: rcvr.PortAddr.Port, 47 Idx: uint8(rcvr.PortAddr.Idx), 48 } 49 50 receiverPortChan, ok := runtimePorts[receiverPortAddr] 51 if !ok { 52 return runtime.Program{}, fmt.Errorf("receiver port not found: %v", receiverPortAddr) 53 } 54 55 meta.ReceiverPortAddrs = append(meta.ReceiverPortAddrs, receiverPortAddr) 56 receiverChans = append(receiverChans, receiverPortChan) 57 } 58 59 runtimeConnections = append(runtimeConnections, runtime.Connection{ 60 Sender: senderPortChan, 61 Receivers: receiverChans, 62 Meta: meta, 63 }) 64 } 65 66 runtimeFuncs := make([]runtime.FuncCall, 0, len(irProg.Funcs)) 67 for _, f := range irProg.Funcs { 68 rIOIn := make(map[string][]chan runtime.Msg, len(f.IO.In)) 69 for _, addr := range f.IO.In { 70 rPort := runtimePorts[runtime.PortAddr{ 71 Path: addr.Path, 72 Port: addr.Port, 73 Idx: uint8(addr.Idx), 74 }] 75 rIOIn[addr.Port] = append(rIOIn[addr.Port], rPort) 76 } 77 78 rIOOut := make(map[string][]chan runtime.Msg, len(f.IO.Out)) 79 for _, addr := range f.IO.Out { 80 rPort := runtimePorts[runtime.PortAddr{ 81 Path: addr.Path, 82 Port: addr.Port, 83 Idx: uint8(addr.Idx), 84 }] 85 rIOOut[addr.Port] = append(rIOOut[addr.Port], rPort) 86 } 87 88 rFunc := runtime.FuncCall{ 89 Ref: f.Ref, 90 IO: runtime.FuncIO{ 91 In: rIOIn, 92 Out: rIOOut, 93 }, 94 } 95 96 if f.Msg != nil { 97 rMsg, err := a.msg(*f.Msg) 98 if err != nil { 99 return runtime.Program{}, fmt.Errorf("msg: %w", err) 100 } 101 rFunc.ConfigMsg = rMsg 102 } 103 104 runtimeFuncs = append(runtimeFuncs, rFunc) 105 } 106 107 return runtime.Program{ 108 Ports: runtimePorts, 109 Connections: runtimeConnections, 110 Funcs: runtimeFuncs, 111 }, nil 112 } 113 114 func (a Adapter) msg(msg ir.Msg) (runtime.Msg, error) { 115 var result runtime.Msg 116 117 switch msg.Type { 118 case ir.MsgTypeBool: 119 result = runtime.NewBoolMsg(msg.Bool) 120 case ir.MsgTypeInt: 121 result = runtime.NewIntMsg(msg.Int) 122 case ir.MsgTypeFloat: 123 result = runtime.NewFloatMsg(msg.Float) 124 case ir.MsgTypeString: 125 result = runtime.NewStrMsg(msg.Str) 126 case ir.MsgTypeList: 127 list := make([]runtime.Msg, len(msg.List)) 128 for i, v := range msg.List { 129 el, err := a.msg(v) 130 if err != nil { 131 return nil, err 132 } 133 list[i] = el 134 } 135 result = runtime.NewListMsg(list...) 136 case ir.MsgTypeMap: 137 m := make(map[string]runtime.Msg, len(msg.List)) 138 for k, v := range msg.Map { 139 el, err := a.msg(v) 140 if err != nil { 141 return nil, err 142 } 143 m[k] = el 144 } 145 result = runtime.NewMapMsg(m) 146 default: 147 return nil, errors.New("unknown message type") 148 } 149 150 return result, nil 151 } 152 153 func NewAdapter() Adapter { 154 return Adapter{} 155 }