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  }