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

     1  package parser
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/nevalang/neva/internal/compiler"
     7  	generated "github.com/nevalang/neva/internal/compiler/parser/generated"
     8  	src "github.com/nevalang/neva/internal/compiler/sourcecode"
     9  	"github.com/nevalang/neva/internal/compiler/sourcecode/core"
    10  )
    11  
    12  var ErrEmptyConnDef error = errors.New("Connection must be either normal or array bypass")
    13  
    14  func parseNet(actx generated.IConnDefListContext) (
    15  	[]src.Connection,
    16  	*compiler.Error,
    17  ) {
    18  	allConnDefs := actx.AllConnDef()
    19  	parsedConns := make([]src.Connection, 0, len(allConnDefs))
    20  
    21  	for _, connDef := range allConnDefs {
    22  		parsedConn, err := parseConn(connDef)
    23  		if err != nil {
    24  			return nil, err
    25  		}
    26  		parsedConns = append(parsedConns, parsedConn...)
    27  	}
    28  
    29  	return parsedConns, nil
    30  }
    31  
    32  func parseConn(connDef generated.IConnDefContext) (
    33  	[]src.Connection,
    34  	*compiler.Error,
    35  ) {
    36  	connMeta := core.Meta{
    37  		Text: connDef.GetText(),
    38  		Start: core.Position{
    39  			Line:   connDef.GetStart().GetLine(),
    40  			Column: connDef.GetStart().GetColumn(),
    41  		},
    42  		Stop: core.Position{
    43  			Line:   connDef.GetStop().GetLine(),
    44  			Column: connDef.GetStop().GetColumn(),
    45  		},
    46  	}
    47  
    48  	normConn := connDef.NormConnDef()
    49  	arrBypassConn := connDef.ArrBypassConnDef()
    50  
    51  	if normConn == nil && arrBypassConn == nil {
    52  		return nil, &compiler.Error{
    53  			Err:  ErrEmptyConnDef,
    54  			Meta: &connMeta,
    55  		}
    56  	}
    57  
    58  	if arrBypassConn != nil {
    59  		return parseArrayBypassConn(arrBypassConn, connMeta)
    60  	}
    61  
    62  	return parseNormConn(normConn, connMeta)
    63  }
    64  
    65  func parseArrayBypassConn(arrBypassConn generated.IArrBypassConnDefContext, connMeta core.Meta) ([]src.Connection, *compiler.Error) {
    66  	senderPortAddr := arrBypassConn.SinglePortAddr(0)
    67  	receiverPortAddr := arrBypassConn.SinglePortAddr(1)
    68  
    69  	senderPortAddrParsed, err := parseSinglePortAddr(
    70  		"in",
    71  		senderPortAddr,
    72  		connMeta,
    73  	)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	receiverPortAddrParsed, err := parseSinglePortAddr(
    79  		"out",
    80  		receiverPortAddr,
    81  		connMeta,
    82  	)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	return []src.Connection{
    88  		{
    89  			ArrayBypass: &src.ArrayBypassConnection{
    90  				SenderOutport:  senderPortAddrParsed,
    91  				ReceiverInport: receiverPortAddrParsed,
    92  			},
    93  			Meta: connMeta,
    94  		},
    95  	}, nil
    96  }
    97  
    98  func parseNormConn(
    99  	normConn generated.INormConnDefContext,
   100  	connMeta core.Meta,
   101  ) ([]src.Connection, *compiler.Error) {
   102  	singleSender := normConn.SenderSide().SingleSenderSide()
   103  	mulSenders := normConn.SenderSide().MultipleSenderSide()
   104  
   105  	if singleSender == nil && mulSenders == nil {
   106  		return nil, &compiler.Error{
   107  			Err: errors.New(
   108  				"Connection must have at least one sender side",
   109  			),
   110  			Meta: &connMeta,
   111  		}
   112  	}
   113  
   114  	senderSides := []src.ConnectionSenderSide{}
   115  	if singleSender != nil {
   116  		parsedSide, err := parseNormConnSenderSide(singleSender)
   117  		if err != nil {
   118  			return nil, err
   119  		}
   120  		senderSides = append(senderSides, parsedSide)
   121  	} else {
   122  		for _, senderSide := range mulSenders.AllSingleSenderSide() {
   123  			parsedSide, err := parseNormConnSenderSide(senderSide)
   124  			if err != nil {
   125  				return nil, err
   126  			}
   127  			senderSides = append(senderSides, parsedSide)
   128  		}
   129  	}
   130  
   131  	receiverSide := normConn.ReceiverSide()
   132  	chainedConn := receiverSide.ChainedNormConn()
   133  	singleReceiverSide := receiverSide.SingleReceiverSide()
   134  	multipleReceiverSide := receiverSide.MultipleReceiverSide()
   135  
   136  	if chainedConn == nil &&
   137  		singleReceiverSide == nil &&
   138  		multipleReceiverSide == nil {
   139  		return nil, &compiler.Error{
   140  			Err:  errors.New("Connection must have a receiver side"),
   141  			Meta: &connMeta,
   142  		}
   143  	}
   144  
   145  	if chainedConn == nil {
   146  		parsedReceiverSide, extraConns, err := parseNormConnReceiverSide(normConn, connMeta)
   147  		if err != nil {
   148  			return nil, compiler.Error{Meta: &connMeta}.Wrap(err)
   149  		}
   150  
   151  		conns := []src.Connection{}
   152  		for _, senderSide := range senderSides {
   153  			conns = append(conns, src.Connection{
   154  				Normal: &src.NormalConnection{
   155  					SenderSide:   senderSide,
   156  					ReceiverSide: parsedReceiverSide,
   157  				},
   158  				Meta: connMeta,
   159  			})
   160  		}
   161  
   162  		conns = append(conns, extraConns...)
   163  
   164  		return conns, nil
   165  	}
   166  
   167  	// --- chained connection ---
   168  
   169  	chainedNormConn := chainedConn.NormConnDef()
   170  	connMeta = core.Meta{
   171  		Text: chainedNormConn.GetText(),
   172  		Start: core.Position{
   173  			Line:   chainedNormConn.GetStart().GetLine(),
   174  			Column: chainedNormConn.GetStart().GetColumn(),
   175  		},
   176  		Stop: core.Position{
   177  			Line:   chainedNormConn.GetStop().GetLine(),
   178  			Column: chainedNormConn.GetStop().GetColumn(),
   179  		},
   180  	}
   181  
   182  	parseChainConnResult, err := parseNormConn(
   183  		chainedNormConn,
   184  		connMeta,
   185  	)
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  
   190  	// chain connections always have 1 sender with normal port addr
   191  	chainSenderPortAddr := parseChainConnResult[0].Normal.SenderSide.PortAddr
   192  
   193  	// now we need to connect all senders to the chain sender
   194  	conns := []src.Connection{}
   195  	for _, senderSide := range senderSides {
   196  		conns = append(conns, src.Connection{
   197  			Normal: &src.NormalConnection{
   198  				SenderSide: senderSide,
   199  				ReceiverSide: src.ConnectionReceiverSide{
   200  					Receivers: []src.ConnectionReceiver{
   201  						{PortAddr: *chainSenderPortAddr},
   202  					},
   203  				},
   204  			},
   205  			Meta: connMeta,
   206  		})
   207  	}
   208  
   209  	// and don't forget the chained connection(s) itself
   210  	conns = append(conns, parseChainConnResult...)
   211  
   212  	return conns, nil
   213  }
   214  
   215  func parseNormConnReceiverSide(
   216  	normConn generated.INormConnDefContext,
   217  	connMeta core.Meta,
   218  ) (src.ConnectionReceiverSide, []src.Connection, *compiler.Error) {
   219  	receiverSide := normConn.ReceiverSide()
   220  	singleReceiverSide := receiverSide.SingleReceiverSide()
   221  	multipleReceiverSide := receiverSide.MultipleReceiverSide()
   222  
   223  	if singleReceiverSide == nil && multipleReceiverSide == nil {
   224  		return src.ConnectionReceiverSide{}, nil, &compiler.Error{
   225  			Err:  errors.New("No receiver side in connection"),
   226  			Meta: &connMeta,
   227  		}
   228  	}
   229  
   230  	if singleReceiverSide != nil {
   231  		return parseReceiverSide(receiverSide, connMeta)
   232  	}
   233  
   234  	multipleSides := receiverSide.MultipleReceiverSide()
   235  	if multipleSides == nil {
   236  		return src.ConnectionReceiverSide{}, nil, &compiler.Error{
   237  			Err: errors.New("no receiver sides at all"),
   238  			Meta: &core.Meta{
   239  				Text: normConn.GetText(),
   240  				Start: core.Position{
   241  					Line:   normConn.GetStart().GetLine(),
   242  					Column: normConn.GetStart().GetColumn(),
   243  				},
   244  				Stop: core.Position{
   245  					Line:   normConn.GetStop().GetLine(),
   246  					Column: normConn.GetStop().GetColumn(),
   247  				},
   248  			},
   249  		}
   250  	}
   251  
   252  	return parseMultipleReceiverSides(multipleSides)
   253  }
   254  
   255  func parseReceiverSide(
   256  	actx generated.IReceiverSideContext,
   257  	connMeta core.Meta,
   258  ) (src.ConnectionReceiverSide, []src.Connection, *compiler.Error) {
   259  	deferredConn := actx.SingleReceiverSide().DeferredConn()
   260  	portAddr := actx.SingleReceiverSide().PortAddr()
   261  
   262  	if deferredConn == nil && portAddr == nil {
   263  		return src.ConnectionReceiverSide{}, nil, &compiler.Error{
   264  			Err:  errors.New("No receiver side in connection"),
   265  			Meta: &connMeta,
   266  		}
   267  	}
   268  
   269  	if deferredConn != nil {
   270  		return parseDeferredConnExpr(deferredConn, connMeta)
   271  	}
   272  
   273  	parsedSingleReceiver, err := parseSingleReceiverSide(portAddr)
   274  	return parsedSingleReceiver, nil, err
   275  }
   276  
   277  func parseMultipleReceiverSides(
   278  	multipleSides generated.IMultipleReceiverSideContext,
   279  ) (
   280  	src.ConnectionReceiverSide,
   281  	[]src.Connection,
   282  	*compiler.Error,
   283  ) {
   284  	allSingleReceiverSides := multipleSides.AllSingleReceiverSide()
   285  	allParsedReceivers := make([]src.ConnectionReceiver, 0, len(allSingleReceiverSides))
   286  	allParsedDeferredConns := make([]src.Connection, 0, len(allSingleReceiverSides))
   287  
   288  	allExtra := []src.Connection{}
   289  
   290  	for _, receiverSide := range allSingleReceiverSides {
   291  		meta := core.Meta{
   292  			Text: receiverSide.GetText(),
   293  			Start: core.Position{
   294  				Line:   receiverSide.GetStart().GetLine(),
   295  				Column: receiverSide.GetStart().GetColumn(),
   296  			},
   297  			Stop: core.Position{
   298  				Line:   receiverSide.GetStop().GetLine(),
   299  				Column: receiverSide.GetStop().GetColumn(),
   300  			},
   301  		}
   302  
   303  		portAddr := receiverSide.PortAddr()
   304  		deferredConns := receiverSide.DeferredConn()
   305  
   306  		if portAddr == nil && deferredConns == nil {
   307  			return src.ConnectionReceiverSide{}, nil, &compiler.Error{
   308  				Err:  errors.New("No receiver side in connection"),
   309  				Meta: &meta,
   310  			}
   311  		}
   312  
   313  		if portAddr != nil {
   314  			portAddr, err := parsePortAddr(receiverSide.PortAddr(), "out")
   315  			if err != nil {
   316  				return src.ConnectionReceiverSide{}, nil, err
   317  			}
   318  			allParsedReceivers = append(allParsedReceivers, src.ConnectionReceiver{
   319  				PortAddr: portAddr,
   320  				Meta:     meta,
   321  			})
   322  			continue
   323  		}
   324  
   325  		parsedDeferredConns, extra, err := parseDeferredConnExpr(deferredConns, meta)
   326  		if err != nil {
   327  			return src.ConnectionReceiverSide{}, nil, &compiler.Error{
   328  				Err:  err,
   329  				Meta: &meta,
   330  			}
   331  		}
   332  
   333  		allParsedDeferredConns = append(allParsedDeferredConns, parsedDeferredConns.DeferredConnections...)
   334  		allExtra = append(allExtra, extra...)
   335  	}
   336  
   337  	return src.ConnectionReceiverSide{
   338  		Receivers:           allParsedReceivers,
   339  		DeferredConnections: allParsedDeferredConns,
   340  	}, allExtra, nil
   341  }
   342  
   343  func parseDeferredConnExpr(
   344  	deferredConns generated.IDeferredConnContext,
   345  	connMeta core.Meta,
   346  ) (src.ConnectionReceiverSide, []src.Connection, *compiler.Error) {
   347  	parsedConns, err := parseConn(deferredConns.ConnDef())
   348  	if err != nil {
   349  		return src.ConnectionReceiverSide{}, nil, &compiler.Error{
   350  			Err:  err,
   351  			Meta: &connMeta,
   352  		}
   353  	}
   354  
   355  	if len(parsedConns) == 1 {
   356  		return src.ConnectionReceiverSide{
   357  			DeferredConnections: parsedConns,
   358  		}, nil, nil
   359  	}
   360  
   361  	// if we have >1 then there was chained connection inside
   362  	return src.ConnectionReceiverSide{
   363  		DeferredConnections: parsedConns[:1],
   364  	}, parsedConns[1:], nil
   365  }
   366  
   367  func parseNormConnSenderSide(
   368  	senderSide generated.ISingleSenderSideContext,
   369  ) (src.ConnectionSenderSide, *compiler.Error) { //nolint:funlen
   370  	var senderSelectors []string
   371  	singleSenderSelectors := senderSide.StructSelectors()
   372  	if singleSenderSelectors != nil {
   373  		for _, id := range singleSenderSelectors.AllIDENTIFIER() {
   374  			senderSelectors = append(senderSelectors, id.GetText())
   375  		}
   376  	}
   377  
   378  	portSender := senderSide.PortAddr()
   379  	constRefSender := senderSide.SenderConstRef()
   380  	primitiveConstLitSender := senderSide.PrimitiveConstLit()
   381  
   382  	if portSender == nil &&
   383  		constRefSender == nil &&
   384  		primitiveConstLitSender == nil {
   385  		return src.ConnectionSenderSide{}, &compiler.Error{
   386  			Err: errors.New("Sender side is missing in connection"),
   387  			Meta: &core.Meta{
   388  				Text: senderSide.GetText(),
   389  				Start: core.Position{
   390  					Line:   senderSide.GetStart().GetLine(),
   391  					Column: senderSide.GetStart().GetColumn(),
   392  				},
   393  				Stop: core.Position{
   394  					Line:   senderSide.GetStop().GetLine(),
   395  					Column: senderSide.GetStop().GetColumn(),
   396  				},
   397  			},
   398  		}
   399  	}
   400  
   401  	var senderSidePortAddr *src.PortAddr
   402  	if portSender != nil {
   403  		parsedPortAddr, err := parsePortAddr(portSender, "in")
   404  		if err != nil {
   405  			return src.ConnectionSenderSide{}, err
   406  		}
   407  		senderSidePortAddr = &parsedPortAddr
   408  	}
   409  
   410  	var constant *src.Const
   411  	if constRefSender != nil {
   412  		parsedEntityRef, err := parseEntityRef(constRefSender.EntityRef())
   413  		if err != nil {
   414  			return src.ConnectionSenderSide{}, err
   415  		}
   416  		constant = &src.Const{
   417  			Ref: &parsedEntityRef,
   418  		}
   419  	}
   420  
   421  	if primitiveConstLitSender != nil {
   422  		msg, err := parsePrimitiveConstLiteral(primitiveConstLitSender)
   423  		if err != nil {
   424  			return src.ConnectionSenderSide{}, err
   425  		}
   426  		constant = &src.Const{Message: &msg}
   427  	}
   428  
   429  	parsedSenderSide := src.ConnectionSenderSide{
   430  		PortAddr:  senderSidePortAddr,
   431  		Const:     constant,
   432  		Selectors: senderSelectors,
   433  		Meta: core.Meta{
   434  			Text: senderSide.GetText(),
   435  			Start: core.Position{
   436  				Line:   senderSide.GetStart().GetLine(),
   437  				Column: senderSide.GetStart().GetColumn(),
   438  			},
   439  			Stop: core.Position{
   440  				Line:   senderSide.GetStop().GetLine(),
   441  				Column: senderSide.GetStop().GetColumn(),
   442  			},
   443  		},
   444  	}
   445  
   446  	return parsedSenderSide, nil
   447  }
   448  
   449  func parseSingleReceiverSide(
   450  	singleReceiver generated.IPortAddrContext,
   451  ) (
   452  	src.ConnectionReceiverSide,
   453  	*compiler.Error,
   454  ) {
   455  	portAddr, err := parsePortAddr(singleReceiver, "out")
   456  	if err != nil {
   457  		return src.ConnectionReceiverSide{}, err
   458  	}
   459  
   460  	return src.ConnectionReceiverSide{
   461  		Receivers: []src.ConnectionReceiver{
   462  			{
   463  				PortAddr: portAddr,
   464  				Meta: core.Meta{
   465  					Text: singleReceiver.GetText(),
   466  					Start: core.Position{
   467  						Line:   singleReceiver.GetStart().GetLine(),
   468  						Column: singleReceiver.GetStart().GetColumn(),
   469  					},
   470  					Stop: core.Position{
   471  						Line:   singleReceiver.GetStop().GetLine(),
   472  						Column: singleReceiver.GetStop().GetColumn(),
   473  					},
   474  				},
   475  			},
   476  		},
   477  	}, nil
   478  }
   479  
   480  // :start -> (99 -> next:n -> match:data)
   481  
   482  // :start -> (99 -> next:n, next:n -> match:data)
   483  
   484  // :start -> (99 -> next:n)
   485  // next:n -> match:data