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

     1  package parser
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/nevalang/neva/internal/compiler"
     7  	src "github.com/nevalang/neva/internal/compiler/sourcecode"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  // userSender.pet.name -> println -> :stop
    12  func TestParser_ParseFile_StructSelectorsWithLonelyChain(t *testing.T) {
    13  	text := []byte(`
    14  		component C1() () {
    15  			userSender.pet.name -> println -> :stop
    16  		}`,
    17  	)
    18  	p := New(false)
    19  	got, err := p.parseFile(src.Location{}, text)
    20  	require.True(t, err == nil)
    21  
    22  	net := got.Entities["C1"].Component.Net
    23  	require.Equal(t, 2, len(net))
    24  
    25  	conn := net[0].Normal
    26  	require.Equal(t, "userSender", conn.SenderSide.PortAddr.Node)
    27  	require.Equal(t, "", conn.SenderSide.PortAddr.Port)
    28  	require.Equal(t, "pet", conn.SenderSide.Selectors[0])
    29  	require.Equal(t, "name", conn.SenderSide.Selectors[1])
    30  	require.Equal(t, "println", conn.ReceiverSide.Receivers[0].PortAddr.Node)
    31  	require.Equal(t, "", conn.ReceiverSide.Receivers[0].PortAddr.Port)
    32  
    33  	conn = net[1].Normal
    34  	require.Equal(t, "println", conn.SenderSide.PortAddr.Node)
    35  	require.Equal(t, "", conn.SenderSide.PortAddr.Port)
    36  	require.Equal(t, "stop", conn.ReceiverSide.Receivers[0].PortAddr.Port)
    37  }
    38  
    39  func TestParser_ParseFile_PortlessArrPortAddr(t *testing.T) {
    40  	text := []byte(`
    41  		component C1() () {
    42  			foo[0] -> bar[255]
    43  		}
    44  	`)
    45  
    46  	p := New(false)
    47  
    48  	got, err := p.parseFile(src.Location{}, text)
    49  	require.Equal(t, true, err == nil)
    50  
    51  	net := got.Entities["C1"].Component.Net
    52  	conn := net[0].Normal
    53  
    54  	// foo[0]->
    55  	require.Equal(t, "foo", conn.SenderSide.PortAddr.Node)
    56  	require.Equal(t, "", conn.SenderSide.PortAddr.Port)
    57  	require.Equal(t, compiler.Pointer(uint8(0)), conn.SenderSide.PortAddr.Idx)
    58  
    59  	// ->bar[255]
    60  	require.Equal(t, "bar", conn.ReceiverSide.Receivers[0].PortAddr.Node)
    61  	require.Equal(t, "", conn.ReceiverSide.Receivers[0].PortAddr.Port)
    62  	require.Equal(t, compiler.Pointer(uint8(255)), conn.ReceiverSide.Receivers[0].PortAddr.Idx)
    63  }
    64  
    65  func TestParser_ParseFile_ChainedConnectionsWithDefer(t *testing.T) {
    66  	text := []byte(`
    67  		component C1() () {
    68  			:start -> (foo -> bar -> :stop)
    69  		}
    70  	`)
    71  
    72  	p := New(false)
    73  
    74  	got, err := p.parseFile(src.Location{}, text)
    75  	require.True(t, err == nil)
    76  
    77  	net := got.Entities["C1"].Component.Net
    78  	require.Equal(t, 2, len(net))
    79  }
    80  
    81  func TestParser_ParseFile_LonelyPorts(t *testing.T) {
    82  	text := []byte(`
    83  		component C1() () {
    84  			:port -> lonely
    85  			lonely -> :port
    86  			:port -> lonely -> :port
    87  		}
    88  	`)
    89  
    90  	p := New(false)
    91  
    92  	got, err := p.parseFile(src.Location{}, text)
    93  	require.True(t, err == nil)
    94  
    95  	// 1) :port -> lonely
    96  	// 2) lonely -> :port
    97  	// 3) :port -> lonely
    98  	// 4) lonely -> :port
    99  	net := got.Entities["C1"].Component.Net
   100  	require.Equal(t, 4, len(net))
   101  
   102  	// 1) :port -> lonely
   103  	receiverPortAddr := net[0].Normal.ReceiverSide.Receivers[0].PortAddr
   104  	require.Equal(t, "lonely", receiverPortAddr.Node)
   105  	require.Equal(t, "", receiverPortAddr.Port)
   106  
   107  	// 2) lonely -> :port
   108  	senderPortAddr := net[1].Normal.SenderSide.PortAddr
   109  	require.Equal(t, "lonely", senderPortAddr.Node)
   110  	require.Equal(t, "", senderPortAddr.Port)
   111  
   112  	// 3) :port -> lonely
   113  	receiverPortAddr = net[2].Normal.ReceiverSide.Receivers[0].PortAddr
   114  	require.Equal(t, "lonely", receiverPortAddr.Node)
   115  	require.Equal(t, "", receiverPortAddr.Port)
   116  
   117  	// 4) lonely -> :port
   118  	senderPortAddr = net[3].Normal.SenderSide.PortAddr
   119  	require.Equal(t, "lonely", senderPortAddr.Node)
   120  	require.Equal(t, "", senderPortAddr.Port)
   121  }
   122  
   123  func TestParser_ParseFile_ChainedConnections(t *testing.T) {
   124  	text := []byte(`
   125  		component C1() () { :in -> n1:p1 -> :out }
   126  	`)
   127  
   128  	p := New(false)
   129  
   130  	got, err := p.parseFile(src.Location{}, text)
   131  	require.True(t, err == nil)
   132  
   133  	net := got.Entities["C1"].Component.Net
   134  	require.Equal(t, 2, len(net))
   135  }
   136  
   137  func TestParser_ParseFile_Comments(t *testing.T) {
   138  	text := []byte(`
   139  	// comment
   140  	`)
   141  
   142  	p := New(false)
   143  
   144  	_, err := p.parseFile(src.Location{}, text)
   145  	require.True(t, err == nil)
   146  }
   147  
   148  func TestParser_ParseFile_Directives(t *testing.T) {
   149  	text := []byte(`
   150  		component {
   151  			#extern(d1)
   152  			C1() ()
   153  
   154  			#extern(d2)
   155  			C2() () {
   156  				nodes {
   157  					#bind(d3)
   158  					n1 C1
   159  
   160  					#bind(d4)
   161  					n2 C1
   162  				}
   163  			}
   164  
   165  			#autoports
   166  			C3() ()
   167  
   168  			#extern(d5)
   169  			#autoports
   170  			C4() ()
   171  		}
   172  	`)
   173  
   174  	p := New(false)
   175  
   176  	got, err := p.parseFile(src.Location{}, text)
   177  	require.True(t, err == nil)
   178  
   179  	d1 := got.Entities["C1"].Component.Directives[compiler.ExternDirective][0]
   180  	require.Equal(t, "d1", d1)
   181  
   182  	c2 := got.Entities["C2"].Component
   183  
   184  	d2 := c2.Directives[compiler.ExternDirective][0]
   185  	require.Equal(t, "d2", d2)
   186  
   187  	d3 := c2.Nodes["n1"].Directives[compiler.BindDirective][0]
   188  	require.Equal(t, "d3", d3)
   189  
   190  	d4 := c2.Nodes["n2"].Directives[compiler.BindDirective][0]
   191  	require.Equal(t, "d4", d4)
   192  
   193  	c3 := got.Entities["C3"].Component
   194  	_, ok := c3.Directives[compiler.AutoportsDirective]
   195  	require.Equal(t, true, ok)
   196  
   197  	c4 := got.Entities["C4"].Component
   198  	d5, ok := c4.Directives[compiler.ExternDirective]
   199  	require.Equal(t, true, ok)
   200  	require.Equal(t, "d5", d5[0])
   201  	_, ok = c4.Directives[compiler.AutoportsDirective]
   202  	require.Equal(t, true, ok)
   203  }
   204  
   205  func TestParser_ParseFile_IONodes(t *testing.T) {
   206  	text := []byte(`
   207  		component C1(start any) (stop any) {
   208  			:start -> :stop
   209  		}
   210  	`)
   211  
   212  	p := New(false)
   213  
   214  	got, err := p.parseFile(src.Location{}, text)
   215  	require.True(t, err == nil)
   216  
   217  	conn := got.Entities["C1"].Component.Net[0]
   218  
   219  	sender := conn.Normal.SenderSide.PortAddr.Node
   220  	require.Equal(t, "in", sender)
   221  
   222  	receiver := conn.Normal.ReceiverSide.Receivers[0].PortAddr.Node
   223  	require.Equal(t, "out", receiver)
   224  }
   225  
   226  func TestParser_ParseFile_AnonymousNodes(t *testing.T) {
   227  	text := []byte(`
   228  		component C1(start any) (stop any) {
   229  			nodes {
   230  				Scanner
   231  				Printer<int>
   232  			}
   233  		}
   234  	`)
   235  
   236  	p := New(false)
   237  
   238  	got, err := p.parseFile(src.Location{}, text)
   239  	require.True(t, err == nil)
   240  
   241  	nodes := got.Entities["C1"].Component.Nodes
   242  
   243  	_, ok := nodes["scanner"]
   244  	require.Equal(t, true, ok)
   245  
   246  	_, ok = nodes["printer"]
   247  	require.Equal(t, true, ok)
   248  }
   249  
   250  func TestParser_ParseFile_EnumLiterals(t *testing.T) {
   251  	text := []byte(`
   252  		const c0 Enum = Enum1::Foo
   253  		const c1 pkg.Enum = pkg.Enum2::Bar
   254  	`)
   255  
   256  	p := New(false)
   257  
   258  	got, err := p.parseFile(src.Location{}, text)
   259  	require.True(t, err == nil)
   260  
   261  	enum := got.Entities["c0"].Const.Message.Enum
   262  	require.Equal(t, "", enum.EnumRef.Pkg)
   263  	require.Equal(t, "Enum1", enum.EnumRef.Name)
   264  	require.Equal(t, "Foo", enum.MemberName)
   265  
   266  	enum = got.Entities["c1"].Const.Message.Enum
   267  	require.Equal(t, "pkg", enum.EnumRef.Pkg)
   268  	require.Equal(t, "Enum2", enum.EnumRef.Name)
   269  	require.Equal(t, "Bar", enum.MemberName)
   270  }
   271  
   272  func TestParser_ParseFile_EnumLiteralSenders(t *testing.T) {
   273  	text := []byte(`
   274  		component C1() () {
   275  			Foo::Bar -> :out
   276  			foo.Bar::Baz -> :out
   277  		}
   278  	`)
   279  
   280  	p := New(false)
   281  
   282  	got, err := p.parseFile(src.Location{}, text)
   283  	require.True(t, err == nil)
   284  
   285  	conn := got.Entities["C1"].Component.Net[0]
   286  
   287  	senderEnum := conn.Normal.SenderSide.Const.Message.Enum
   288  	require.Equal(t, "", senderEnum.EnumRef.Pkg)
   289  	require.Equal(t, "Foo", senderEnum.EnumRef.Name)
   290  	require.Equal(t, "Bar", senderEnum.MemberName)
   291  
   292  	conn = got.Entities["C1"].Component.Net[1]
   293  	senderEnum = conn.Normal.SenderSide.Const.Message.Enum
   294  	require.Equal(t, "foo", senderEnum.EnumRef.Pkg)
   295  	require.Equal(t, "Bar", senderEnum.EnumRef.Name)
   296  	require.Equal(t, "Baz", senderEnum.MemberName)
   297  }