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 }