github.com/nevalang/neva@v0.23.1-0.20240507185603-7696a9bb8dda/internal/compiler/desugarer/node.go (about)

     1  package desugarer
     2  
     3  import (
     4  	"fmt"
     5  	"maps"
     6  
     7  	"github.com/nevalang/neva/internal/compiler"
     8  	src "github.com/nevalang/neva/internal/compiler/sourcecode"
     9  	"github.com/nevalang/neva/internal/compiler/sourcecode/core"
    10  )
    11  
    12  func (Desugarer) handleNode(
    13  	scope src.Scope,
    14  	node src.Node,
    15  	desugaredNodes map[string]src.Node,
    16  	nodeName string,
    17  	virtualEntities map[string]src.Entity,
    18  ) ([]src.Connection, *compiler.Error) {
    19  	var extraConnections []src.Connection
    20  
    21  	if node.ErrGuard {
    22  		extraConnections = append(extraConnections, src.Connection{
    23  			Normal: &src.NormalConnection{
    24  				SenderSide: src.ConnectionSenderSide{
    25  					PortAddr: &src.PortAddr{
    26  						Node: nodeName,
    27  						Port: "err",
    28  					},
    29  				},
    30  				ReceiverSide: src.ConnectionReceiverSide{
    31  					Receivers: []src.ConnectionReceiver{
    32  						{
    33  							PortAddr: src.PortAddr{
    34  								Node: "out",
    35  								Port: "err",
    36  							},
    37  						},
    38  					},
    39  				},
    40  			},
    41  		})
    42  	}
    43  
    44  	entity, _, err := scope.Entity(node.EntityRef)
    45  	if err != nil {
    46  		return nil, &compiler.Error{
    47  			Err:      err,
    48  			Location: &scope.Location,
    49  		}
    50  	}
    51  
    52  	if entity.Kind != src.ComponentEntity {
    53  		desugaredNodes[nodeName] = node
    54  		return extraConnections, nil
    55  	}
    56  
    57  	_, hasAutoports := entity.
    58  		Component.
    59  		Directives[compiler.AutoportsDirective]
    60  
    61  	// nothing to desugar
    62  	if !hasAutoports && len(node.Deps) != 1 {
    63  		desugaredNodes[nodeName] = node
    64  		return extraConnections, nil
    65  	}
    66  
    67  	// --- anon dep ---
    68  
    69  	depArg, ok := node.Deps[""]
    70  	if ok {
    71  		for depParamName, depParam := range entity.Component.Nodes {
    72  			depEntity, _, err := scope.Entity(depParam.EntityRef)
    73  			if err != nil {
    74  				panic(err)
    75  			}
    76  			if depEntity.Kind == src.InterfaceEntity {
    77  				desugaredDeps := maps.Clone(node.Deps)
    78  				desugaredDeps[depParamName] = depArg
    79  				node = src.Node{
    80  					Directives: node.Directives,
    81  					EntityRef:  node.EntityRef,
    82  					TypeArgs:   node.TypeArgs,
    83  					Deps:       desugaredDeps,
    84  					Meta:       node.Meta,
    85  				}
    86  				break
    87  			}
    88  		}
    89  	}
    90  
    91  	if !hasAutoports {
    92  		desugaredNodes[nodeName] = node
    93  		return extraConnections, nil
    94  	}
    95  
    96  	// --- autoports ---
    97  
    98  	structFields := node.TypeArgs[0].Lit.Struct
    99  
   100  	inports := make(map[string]src.Port, len(structFields))
   101  	for fieldName, fieldTypeExpr := range structFields {
   102  		inports[fieldName] = src.Port{
   103  			TypeExpr: fieldTypeExpr,
   104  		}
   105  	}
   106  
   107  	outports := map[string]src.Port{
   108  		"msg": {
   109  			TypeExpr: node.TypeArgs[0],
   110  		},
   111  	}
   112  
   113  	localBuilderComponent := src.Component{
   114  		Interface: src.Interface{
   115  			IO: src.IO{In: inports, Out: outports},
   116  		},
   117  	}
   118  
   119  	localBuilderName := fmt.Sprintf("struct_%v", nodeName)
   120  
   121  	virtualEntities[localBuilderName] = src.Entity{
   122  		Kind:      src.ComponentEntity,
   123  		Component: localBuilderComponent,
   124  	}
   125  
   126  	desugaredNodes[nodeName] = src.Node{
   127  		EntityRef: core.EntityRef{
   128  			Pkg:  "",
   129  			Name: "Struct",
   130  		},
   131  		Directives: node.Directives,
   132  		TypeArgs:   node.TypeArgs,
   133  		Deps:       node.Deps,
   134  		Meta:       node.Meta,
   135  	}
   136  
   137  	return extraConnections, nil
   138  }