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

     1  package parser
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/antlr4-go/antlr/v4"
    10  	"github.com/nevalang/neva/internal/compiler"
    11  	generated "github.com/nevalang/neva/internal/compiler/parser/generated"
    12  	src "github.com/nevalang/neva/internal/compiler/sourcecode"
    13  	"github.com/nevalang/neva/internal/compiler/sourcecode/core"
    14  	ts "github.com/nevalang/neva/internal/compiler/sourcecode/typesystem"
    15  )
    16  
    17  func parseTypeParams(
    18  	params generated.ITypeParamsContext,
    19  ) (src.TypeParams, *compiler.Error) {
    20  	if params == nil || params.TypeParamList() == nil {
    21  		return src.TypeParams{}, nil
    22  	}
    23  
    24  	typeParams := params.TypeParamList().AllTypeParam()
    25  	result := make([]ts.Param, 0, len(typeParams))
    26  	for _, typeParam := range typeParams {
    27  		v, err := parseTypeExpr(typeParam.TypeExpr())
    28  		if err != nil {
    29  			return src.TypeParams{}, err
    30  		}
    31  		result = append(result, ts.Param{
    32  			Name:   typeParam.IDENTIFIER().GetText(),
    33  			Constr: v,
    34  		})
    35  	}
    36  
    37  	return src.TypeParams{
    38  		Params: result,
    39  		Meta: core.Meta{
    40  			Text: params.GetText(),
    41  			Start: core.Position{
    42  				Line:   params.GetStart().GetLine(),
    43  				Column: params.GetStart().GetColumn(),
    44  			},
    45  			Stop: core.Position{
    46  				Line:   params.GetStop().GetLine(),
    47  				Column: params.GetStop().GetColumn(),
    48  			},
    49  		},
    50  	}, nil
    51  }
    52  
    53  func parseTypeExpr(expr generated.ITypeExprContext) (ts.Expr, *compiler.Error) {
    54  	if expr == nil {
    55  		return ts.Expr{
    56  			Inst: &ts.InstExpr{
    57  				Ref: core.EntityRef{Name: "any"},
    58  			},
    59  			Meta: core.Meta{Text: "any"},
    60  		}, nil
    61  	}
    62  
    63  	var result *ts.Expr
    64  	if instExpr := expr.TypeInstExpr(); instExpr != nil {
    65  		v, err := parseTypeInstExpr(instExpr)
    66  		if err != nil {
    67  			return ts.Expr{}, &compiler.Error{
    68  				Err: err,
    69  				Meta: &core.Meta{
    70  					Text: expr.GetText(),
    71  					Start: core.Position{
    72  						Line:   expr.GetStart().GetLine(),
    73  						Column: expr.GetStart().GetColumn(),
    74  					},
    75  					Stop: core.Position{
    76  						Line:   expr.GetStop().GetLine(),
    77  						Column: expr.GetStop().GetColumn(),
    78  					},
    79  				},
    80  			}
    81  		}
    82  		result = v
    83  	} else if unionExpr := expr.UnionTypeExpr(); unionExpr != nil {
    84  		v, err := parseUnionExpr(unionExpr)
    85  		if err != nil {
    86  			return ts.Expr{}, err
    87  		}
    88  		result = v
    89  	} else if litExpr := expr.TypeLitExpr(); litExpr != nil {
    90  		v, err := parseLitExpr(litExpr)
    91  		if err != nil {
    92  			return ts.Expr{}, err
    93  		}
    94  		result = v
    95  	} else {
    96  		return ts.Expr{}, &compiler.Error{
    97  			Err: errors.New("Missing type expression"),
    98  			Meta: &core.Meta{
    99  				Text: expr.GetText(),
   100  				Start: core.Position{
   101  					Line:   expr.GetStart().GetLine(),
   102  					Column: expr.GetStart().GetLine(),
   103  				},
   104  				Stop: core.Position{
   105  					Line:   expr.GetStop().GetLine(),
   106  					Column: expr.GetStop().GetLine(),
   107  				},
   108  			},
   109  		}
   110  	}
   111  
   112  	result.Meta = getTypeExprMeta(expr)
   113  
   114  	return *result, nil
   115  }
   116  
   117  func getTypeExprMeta(expr generated.ITypeExprContext) core.Meta {
   118  	var text string
   119  	if text = expr.GetText(); text == "" {
   120  		text = "any "
   121  	}
   122  
   123  	start := expr.GetStart()
   124  	stop := expr.GetStop()
   125  	meta := core.Meta{
   126  		Text: text,
   127  		Start: core.Position{
   128  			Line:   start.GetLine(),
   129  			Column: start.GetColumn(),
   130  		},
   131  		Stop: core.Position{
   132  			Line:   stop.GetLine(),
   133  			Column: stop.GetColumn(),
   134  		},
   135  	}
   136  	return meta
   137  }
   138  
   139  func parseUnionExpr(unionExpr generated.IUnionTypeExprContext) (*ts.Expr, *compiler.Error) {
   140  	subExprs := unionExpr.AllNonUnionTypeExpr()
   141  	parsedSubExprs := make([]ts.Expr, 0, len(subExprs))
   142  
   143  	for _, subExpr := range subExprs {
   144  		if instExpr := subExpr.TypeInstExpr(); instExpr != nil {
   145  			parsedTypeInstExpr, err := parseTypeInstExpr(instExpr)
   146  			if err != nil {
   147  				return nil, err
   148  			}
   149  			parsedSubExprs = append(parsedSubExprs, *parsedTypeInstExpr)
   150  		}
   151  		if unionExpr := subExpr.TypeLitExpr(); unionExpr != nil {
   152  			v, err := parseLitExpr(subExpr.TypeLitExpr())
   153  			if err != nil {
   154  				return nil, err
   155  			}
   156  			parsedSubExprs = append(parsedSubExprs, *v)
   157  		}
   158  	}
   159  
   160  	return &ts.Expr{
   161  		Lit: &ts.LitExpr{
   162  			Union: parsedSubExprs,
   163  		},
   164  	}, nil
   165  }
   166  
   167  func parseLitExpr(litExpr generated.ITypeLitExprContext) (*ts.Expr, *compiler.Error) {
   168  	enumExpr := litExpr.EnumTypeExpr()
   169  	structExpr := litExpr.StructTypeExpr()
   170  
   171  	switch {
   172  	case enumExpr != nil:
   173  		return parseEnumExpr(enumExpr), nil
   174  	case structExpr != nil:
   175  		return parseStructExpr(structExpr)
   176  	}
   177  
   178  	return nil, &compiler.Error{
   179  		Err: errors.New("Unknown literal type"),
   180  		Meta: &core.Meta{
   181  			Text: litExpr.GetText(),
   182  			Start: core.Position{
   183  				Line:   litExpr.GetStart().GetLine(),
   184  				Column: litExpr.GetStart().GetColumn(),
   185  			},
   186  			Stop: core.Position{
   187  				Line:   litExpr.GetStop().GetLine(),
   188  				Column: litExpr.GetStop().GetColumn(),
   189  			},
   190  		},
   191  	}
   192  }
   193  
   194  func parseEnumExpr(enumExpr generated.IEnumTypeExprContext) *ts.Expr {
   195  	ids := enumExpr.AllIDENTIFIER()
   196  	result := ts.Expr{
   197  		Lit: &ts.LitExpr{
   198  			Enum: make([]string, 0, len(ids)),
   199  		},
   200  	}
   201  	for _, id := range ids {
   202  		result.Lit.Enum = append(result.Lit.Enum, id.GetText())
   203  	}
   204  	return &result
   205  }
   206  
   207  func parseStructExpr(
   208  	structExpr generated.IStructTypeExprContext,
   209  ) (*ts.Expr, *compiler.Error) {
   210  	result := ts.Expr{
   211  		Lit: &ts.LitExpr{
   212  			Struct: map[string]ts.Expr{},
   213  		},
   214  	}
   215  
   216  	structFields := structExpr.StructFields()
   217  	if structFields == nil {
   218  		return &result, nil
   219  	}
   220  
   221  	fields := structExpr.StructFields().AllStructField()
   222  	result.Lit.Struct = make(map[string]ts.Expr, len(fields))
   223  
   224  	for _, field := range fields {
   225  		fieldName := field.IDENTIFIER().GetText()
   226  		v, err := parseTypeExpr(field.TypeExpr())
   227  		if err != nil {
   228  			return nil, err
   229  		}
   230  		result.Lit.Struct[fieldName] = v
   231  	}
   232  
   233  	return &result, nil
   234  }
   235  
   236  func parseTypeInstExpr(instExpr generated.ITypeInstExprContext) (*ts.Expr, *compiler.Error) {
   237  	parsedRef, err := parseEntityRef(instExpr.EntityRef())
   238  	if err != nil {
   239  		return nil, &compiler.Error{
   240  			Err: err,
   241  			Meta: &core.Meta{
   242  				Text: instExpr.GetText(),
   243  				Start: core.Position{
   244  					Line:   instExpr.GetStart().GetLine(),
   245  					Column: instExpr.GetStart().GetColumn(),
   246  				},
   247  				Stop: core.Position{
   248  					Line:   instExpr.GetStop().GetLine(),
   249  					Column: instExpr.GetStop().GetColumn(),
   250  				},
   251  			},
   252  		}
   253  	}
   254  
   255  	result := ts.Expr{
   256  		Inst: &ts.InstExpr{
   257  			Ref: parsedRef,
   258  		},
   259  	}
   260  
   261  	args := instExpr.TypeArgs()
   262  	if args == nil {
   263  		return &result, nil
   264  	}
   265  
   266  	argExprs := args.AllTypeExpr()
   267  	parsedArgs := make([]ts.Expr, 0, len(argExprs))
   268  	for _, arg := range argExprs {
   269  		v, err := parseTypeExpr(arg)
   270  		if err != nil {
   271  			return nil, err
   272  		}
   273  		parsedArgs = append(parsedArgs, v)
   274  	}
   275  	result.Inst.Args = parsedArgs
   276  
   277  	return &result, nil
   278  }
   279  
   280  func parseEntityRef(expr generated.IEntityRefContext) (core.EntityRef, *compiler.Error) {
   281  	meta := core.Meta{
   282  		Text: expr.GetText(),
   283  		Start: core.Position{
   284  			Line:   expr.GetStart().GetLine(),
   285  			Column: expr.GetStart().GetColumn(),
   286  		},
   287  		Stop: core.Position{
   288  			Line:   expr.GetStart().GetLine(),
   289  			Column: expr.GetStop().GetColumn(),
   290  		},
   291  	}
   292  
   293  	parts := strings.Split(expr.GetText(), ".")
   294  	if len(parts) > 2 {
   295  		return core.EntityRef{}, &compiler.Error{
   296  			Err:  fmt.Errorf("Invalid entity reference %v", expr.GetText()),
   297  			Meta: &meta,
   298  		}
   299  	}
   300  
   301  	if len(parts) == 1 {
   302  		return core.EntityRef{
   303  			Name: parts[0],
   304  			Meta: meta,
   305  		}, nil
   306  	}
   307  
   308  	return core.EntityRef{
   309  		Pkg:  parts[0],
   310  		Name: parts[1],
   311  		Meta: meta,
   312  	}, nil
   313  }
   314  
   315  func parsePorts(
   316  	in []generated.IPortDefContext,
   317  ) (map[string]src.Port, *compiler.Error) {
   318  	parsedInports := map[string]src.Port{}
   319  	for _, port := range in {
   320  		single := port.SinglePortDef()
   321  		arr := port.ArrayPortDef()
   322  
   323  		var (
   324  			id       antlr.TerminalNode
   325  			typeExpr generated.ITypeExprContext
   326  			isArr    bool
   327  		)
   328  		if single != nil {
   329  			isArr = false
   330  			id = single.IDENTIFIER()
   331  			typeExpr = single.TypeExpr()
   332  		} else {
   333  			isArr = true
   334  			id = arr.IDENTIFIER()
   335  			typeExpr = arr.TypeExpr()
   336  		}
   337  
   338  		portName := id.GetText()
   339  		v, err := parseTypeExpr(typeExpr)
   340  		if err != nil {
   341  			return nil, err
   342  		}
   343  		parsedInports[portName] = src.Port{
   344  			IsArray:  isArr,
   345  			TypeExpr: v,
   346  			Meta: core.Meta{
   347  				Text: port.GetText(),
   348  				Start: core.Position{
   349  					Line:   port.GetStart().GetLine(),
   350  					Column: port.GetStart().GetColumn(),
   351  				},
   352  				Stop: core.Position{
   353  					Line:   port.GetStop().GetLine(),
   354  					Column: port.GetStop().GetColumn(),
   355  				},
   356  			},
   357  		}
   358  	}
   359  
   360  	return parsedInports, nil
   361  }
   362  
   363  func parseInterfaceDef(
   364  	actx generated.IInterfaceDefContext,
   365  ) (src.Interface, *compiler.Error) {
   366  	parsedTypeParams, err := parseTypeParams(actx.TypeParams())
   367  	if err != nil {
   368  		return src.Interface{}, err
   369  	}
   370  	in, err := parsePorts(actx.InPortsDef().PortsDef().AllPortDef())
   371  	if err != nil {
   372  		return src.Interface{}, err
   373  	}
   374  	out, err := parsePorts(actx.OutPortsDef().PortsDef().AllPortDef())
   375  	if err != nil {
   376  		return src.Interface{}, err
   377  	}
   378  
   379  	return src.Interface{
   380  		TypeParams: parsedTypeParams,
   381  		IO:         src.IO{In: in, Out: out},
   382  		Meta: core.Meta{
   383  			Text: actx.GetText(),
   384  			Start: core.Position{
   385  				Line:   actx.GetStart().GetLine(),
   386  				Column: actx.GetStart().GetColumn(),
   387  			},
   388  			Stop: core.Position{
   389  				Line:   actx.GetStop().GetLine(),
   390  				Column: actx.GetStop().GetColumn(),
   391  			},
   392  		},
   393  	}, nil
   394  }
   395  
   396  func parseNodes(
   397  	actx generated.ICompNodesDefBodyContext,
   398  	isRootLevel bool,
   399  ) (map[string]src.Node, *compiler.Error) {
   400  	result := map[string]src.Node{}
   401  
   402  	for _, node := range actx.AllCompNodeDef() {
   403  		nodeInst := node.NodeInst()
   404  
   405  		directives := parseCompilerDirectives(node.CompilerDirectives())
   406  
   407  		parsedRef, err := parseEntityRef(nodeInst.EntityRef())
   408  		if err != nil {
   409  			return nil, &compiler.Error{
   410  				Err: err,
   411  				Meta: &core.Meta{
   412  					Text: node.GetText(),
   413  					Start: core.Position{
   414  						Line:   node.GetStart().GetLine(),
   415  						Column: node.GetStart().GetColumn(),
   416  					},
   417  					Stop: core.Position{
   418  						Line:   node.GetStop().GetLine(),
   419  						Column: node.GetStop().GetColumn(),
   420  					},
   421  				},
   422  			}
   423  		}
   424  
   425  		var typeArgs []ts.Expr
   426  		if args := nodeInst.TypeArgs(); args != nil {
   427  			v, err := parseTypeExprs(args.AllTypeExpr())
   428  			if err != nil {
   429  				return nil, err
   430  			}
   431  			typeArgs = v
   432  		}
   433  
   434  		var errGuard bool
   435  		if nodeInst.ErrGuard() != nil {
   436  			errGuard = true
   437  		}
   438  
   439  		var deps map[string]src.Node
   440  		if diArgs := nodeInst.NodeDIArgs(); diArgs != nil {
   441  			v, err := parseNodes(diArgs.CompNodesDefBody(), false)
   442  			if err != nil {
   443  				return nil, err
   444  			}
   445  			deps = v
   446  		}
   447  
   448  		var nodeName string
   449  		if id := node.IDENTIFIER(); id != nil {
   450  			nodeName = id.GetText()
   451  		} else if isRootLevel {
   452  			nodeName = strings.ToLower(string(parsedRef.Name[0])) + parsedRef.Name[1:]
   453  		}
   454  
   455  		result[nodeName] = src.Node{
   456  			Directives: directives,
   457  			EntityRef:  parsedRef,
   458  			TypeArgs:   typeArgs,
   459  			ErrGuard:   errGuard,
   460  			Deps:       deps,
   461  			Meta: core.Meta{
   462  				Text: node.GetText(),
   463  				Start: core.Position{
   464  					Line:   node.GetStart().GetLine(),
   465  					Column: node.GetStart().GetColumn(),
   466  				},
   467  				Stop: core.Position{
   468  					Line:   node.GetStop().GetLine(),
   469  					Column: node.GetStop().GetColumn(),
   470  				},
   471  			},
   472  		}
   473  	}
   474  
   475  	return result, nil
   476  }
   477  
   478  func parseTypeExprs(
   479  	in []generated.ITypeExprContext,
   480  ) ([]ts.Expr, *compiler.Error) {
   481  	result := make([]ts.Expr, 0, len(in))
   482  
   483  	for _, expr := range in {
   484  		v, err := parseTypeExpr(expr)
   485  		if err != nil {
   486  			return nil, err
   487  		}
   488  		result = append(result, v)
   489  	}
   490  
   491  	return result, nil
   492  }
   493  
   494  func parsePortAddr(
   495  	expr generated.IPortAddrContext,
   496  	fallbackNode string,
   497  ) (src.PortAddr, *compiler.Error) {
   498  	meta := core.Meta{
   499  		Text: expr.GetText(),
   500  		Start: core.Position{
   501  			Line:   expr.GetStart().GetLine(),
   502  			Column: expr.GetStart().GetColumn(),
   503  		},
   504  		Stop: core.Position{
   505  			Line:   expr.GetStart().GetLine(),
   506  			Column: expr.GetStop().GetColumn(),
   507  		},
   508  	}
   509  
   510  	if expr.ArrPortAddr() == nil &&
   511  		expr.SinglePortAddr() == nil &&
   512  		expr.LonelySinglePortAddr() == nil &&
   513  		expr.LonelyArrPortAddr() == nil {
   514  		return src.PortAddr{}, &compiler.Error{
   515  			Err:  fmt.Errorf("Invalid port address %v", expr.GetText()),
   516  			Meta: &meta,
   517  		}
   518  	}
   519  
   520  	if expr.LonelyArrPortAddr() != nil {
   521  		idxStr := expr.LonelyArrPortAddr().PortAddrIdx()
   522  		withoutSquareBraces := strings.Trim(idxStr.GetText(), "[]")
   523  
   524  		idxUint, err := strconv.ParseUint(
   525  			withoutSquareBraces,
   526  			10,
   527  			8,
   528  		)
   529  		if err != nil {
   530  			return src.PortAddr{}, &compiler.Error{
   531  				Err:  err,
   532  				Meta: &meta,
   533  			}
   534  		}
   535  
   536  		idxUint8 := uint8(idxUint)
   537  
   538  		return src.PortAddr{
   539  			Node: expr.LonelyArrPortAddr().PortAddrNode().GetText(),
   540  			Port: "",
   541  			Idx:  &idxUint8,
   542  			Meta: meta,
   543  		}, nil
   544  	}
   545  
   546  	if expr.LonelySinglePortAddr() != nil {
   547  		return src.PortAddr{
   548  			Node: expr.LonelySinglePortAddr().PortAddrNode().GetText(),
   549  			Port: "",
   550  			// Idx:  &idxUint8,
   551  			Meta: meta,
   552  		}, nil
   553  	}
   554  
   555  	if expr.SinglePortAddr() != nil {
   556  		return parseSinglePortAddr(fallbackNode, expr.SinglePortAddr(), meta)
   557  	}
   558  
   559  	idxStr := expr.ArrPortAddr().PortAddrIdx()
   560  	withoutSquareBraces := strings.Trim(idxStr.GetText(), "[]")
   561  
   562  	idxUint, err := strconv.ParseUint(
   563  		withoutSquareBraces,
   564  		10,
   565  		8,
   566  	)
   567  	if err != nil {
   568  		return src.PortAddr{}, &compiler.Error{
   569  			Err:  err,
   570  			Meta: &meta,
   571  		}
   572  	}
   573  
   574  	nodeName := fallbackNode
   575  	if n := expr.ArrPortAddr().PortAddrNode(); n != nil {
   576  		nodeName = n.GetText()
   577  	}
   578  
   579  	idxUint8 := uint8(idxUint)
   580  
   581  	return src.PortAddr{
   582  		Idx:  &idxUint8,
   583  		Node: nodeName,
   584  		Port: expr.ArrPortAddr().PortAddrPort().GetText(),
   585  		Meta: meta,
   586  	}, nil
   587  
   588  }
   589  
   590  func parseSinglePortAddr(
   591  	fallbackNode string,
   592  	expr generated.ISinglePortAddrContext,
   593  	meta core.Meta,
   594  ) (src.PortAddr, *compiler.Error) {
   595  	nodeName := fallbackNode
   596  	if n := expr.PortAddrNode(); n != nil {
   597  		nodeName = n.GetText()
   598  	}
   599  
   600  	return src.PortAddr{
   601  		Node: nodeName,
   602  		Port: expr.PortAddrPort().GetText(),
   603  		Meta: meta,
   604  	}, nil
   605  }
   606  
   607  func parsePrimitiveConstLiteral(
   608  	lit generated.IPrimitiveConstLitContext,
   609  ) (src.Message, *compiler.Error) {
   610  	msg := src.Message{
   611  		Meta: core.Meta{
   612  			Text: lit.GetText(),
   613  			Start: core.Position{
   614  				Line:   lit.GetStart().GetLine(),
   615  				Column: lit.GetStart().GetColumn(),
   616  			},
   617  			Stop: core.Position{
   618  				Line:   lit.GetStop().GetLine(),
   619  				Column: lit.GetStop().GetColumn(),
   620  			},
   621  		},
   622  	}
   623  
   624  	switch {
   625  	case lit.Bool_() != nil:
   626  		boolVal := lit.Bool_().GetText()
   627  		if boolVal != "true" && boolVal != "false" {
   628  			return src.Message{}, &compiler.Error{
   629  				Err: fmt.Errorf("Invalid boolean value %v", boolVal),
   630  				Meta: &core.Meta{
   631  					Text: lit.GetText(),
   632  					Start: core.Position{
   633  						Line:   lit.GetStart().GetLine(),
   634  						Column: lit.GetStart().GetColumn(),
   635  					},
   636  					Stop: core.Position{
   637  						Line:   lit.GetStop().GetLine(),
   638  						Column: lit.GetStop().GetColumn(),
   639  					},
   640  				},
   641  			}
   642  		}
   643  		msg.TypeExpr.Inst = &ts.InstExpr{
   644  			Ref: core.EntityRef{Name: "bool"},
   645  		}
   646  		msg.Bool = compiler.Pointer(boolVal == "true")
   647  	case lit.INT() != nil:
   648  		parsedInt, err := strconv.ParseInt(lit.INT().GetText(), 10, 64)
   649  		if err != nil {
   650  			return src.Message{}, &compiler.Error{
   651  				Err:      err,
   652  				Location: &src.Location{},
   653  				Meta: &core.Meta{
   654  					Text: lit.GetText(),
   655  					Start: core.Position{
   656  						Line:   lit.GetStart().GetLine(),
   657  						Column: lit.GetStart().GetColumn(),
   658  					},
   659  					Stop: core.Position{
   660  						Line:   lit.GetStop().GetLine(),
   661  						Column: lit.GetStop().GetColumn(),
   662  					},
   663  				},
   664  			}
   665  		}
   666  		msg.TypeExpr.Inst = &ts.InstExpr{
   667  			Ref: core.EntityRef{Name: "int"},
   668  		}
   669  		if lit.MINUS() != nil {
   670  			parsedInt = -parsedInt
   671  		}
   672  		msg.Int = compiler.Pointer(int(parsedInt))
   673  	case lit.FLOAT() != nil:
   674  		parsedFloat, err := strconv.ParseFloat(lit.FLOAT().GetText(), 64)
   675  		if err != nil {
   676  			return src.Message{}, &compiler.Error{
   677  				Err: err,
   678  				Meta: &core.Meta{
   679  					Text: lit.GetText(),
   680  					Start: core.Position{
   681  						Line:   lit.GetStart().GetLine(),
   682  						Column: lit.GetStart().GetColumn(),
   683  					},
   684  					Stop: core.Position{
   685  						Line:   lit.GetStop().GetLine(),
   686  						Column: lit.GetStop().GetColumn(),
   687  					},
   688  				},
   689  			}
   690  		}
   691  		msg.TypeExpr.Inst = &ts.InstExpr{
   692  			Ref: core.EntityRef{Name: "float"},
   693  		}
   694  		if lit.MINUS() != nil {
   695  			parsedFloat = -parsedFloat
   696  		}
   697  		msg.Float = &parsedFloat
   698  	case lit.STRING() != nil:
   699  		msg.Str = compiler.Pointer(
   700  			strings.Trim(
   701  				strings.ReplaceAll(
   702  					lit.STRING().GetText(),
   703  					"\\n",
   704  					"\n",
   705  				),
   706  				"'",
   707  			),
   708  		)
   709  		msg.TypeExpr.Inst = &ts.InstExpr{
   710  			Ref: core.EntityRef{Name: "string"},
   711  		}
   712  	case lit.EnumLit() != nil:
   713  		parsedEnumRef, err := parseEntityRef(lit.EnumLit().EntityRef())
   714  		if err != nil {
   715  			return src.Message{}, err
   716  		}
   717  		msg.Enum = &src.EnumMessage{
   718  			EnumRef:    parsedEnumRef,
   719  			MemberName: lit.EnumLit().IDENTIFIER().GetText(),
   720  		}
   721  		msg.TypeExpr = ts.Expr{
   722  			Inst: &ts.InstExpr{Ref: parsedEnumRef},
   723  			Meta: parsedEnumRef.Meta,
   724  		}
   725  	case lit.Nil_() != nil:
   726  		return src.Message{}, nil
   727  	default:
   728  		panic("unknown const: " + lit.GetText())
   729  	}
   730  
   731  	return msg, nil
   732  }
   733  
   734  func parseMessage(
   735  	constVal generated.IConstLitContext,
   736  ) (src.Message, *compiler.Error) {
   737  	msg := src.Message{
   738  		Meta: core.Meta{
   739  			Text: constVal.GetText(),
   740  			Start: core.Position{
   741  				Line:   constVal.GetStart().GetLine(),
   742  				Column: constVal.GetStart().GetColumn(),
   743  			},
   744  			Stop: core.Position{
   745  				Line:   constVal.GetStop().GetLine(),
   746  				Column: constVal.GetStop().GetColumn(),
   747  			},
   748  		},
   749  	}
   750  
   751  	switch {
   752  	case constVal.Bool_() != nil:
   753  		boolVal := constVal.Bool_().GetText()
   754  		if boolVal != "true" && boolVal != "false" {
   755  			return src.Message{}, &compiler.Error{
   756  				Err: fmt.Errorf("Invalid boolean value %v", boolVal),
   757  				Meta: &core.Meta{
   758  					Text: constVal.GetText(),
   759  					Start: core.Position{
   760  						Line:   constVal.GetStart().GetLine(),
   761  						Column: constVal.GetStart().GetColumn(),
   762  					},
   763  					Stop: core.Position{
   764  						Line:   constVal.GetStop().GetLine(),
   765  						Column: constVal.GetStop().GetColumn(),
   766  					},
   767  				},
   768  			}
   769  		}
   770  		msg.TypeExpr.Inst = &ts.InstExpr{
   771  			Ref: core.EntityRef{Name: "bool"},
   772  		}
   773  		msg.Bool = compiler.Pointer(boolVal == "true")
   774  	case constVal.INT() != nil:
   775  		parsedInt, err := strconv.ParseInt(constVal.INT().GetText(), 10, 64)
   776  		if err != nil {
   777  			return src.Message{}, &compiler.Error{
   778  				Err:      err,
   779  				Location: &src.Location{},
   780  				Meta: &core.Meta{
   781  					Text: constVal.GetText(),
   782  					Start: core.Position{
   783  						Line:   constVal.GetStart().GetLine(),
   784  						Column: constVal.GetStart().GetColumn(),
   785  					},
   786  					Stop: core.Position{
   787  						Line:   constVal.GetStop().GetLine(),
   788  						Column: constVal.GetStop().GetColumn(),
   789  					},
   790  				},
   791  			}
   792  		}
   793  		msg.TypeExpr.Inst = &ts.InstExpr{
   794  			Ref: core.EntityRef{Name: "int"},
   795  		}
   796  		if constVal.MINUS() != nil {
   797  			parsedInt = -parsedInt
   798  		}
   799  		msg.Int = compiler.Pointer(int(parsedInt))
   800  	case constVal.FLOAT() != nil:
   801  		parsedFloat, err := strconv.ParseFloat(constVal.FLOAT().GetText(), 64)
   802  		if err != nil {
   803  			return src.Message{}, &compiler.Error{
   804  				Err: err,
   805  				Meta: &core.Meta{
   806  					Text: constVal.GetText(),
   807  					Start: core.Position{
   808  						Line:   constVal.GetStart().GetLine(),
   809  						Column: constVal.GetStart().GetColumn(),
   810  					},
   811  					Stop: core.Position{
   812  						Line:   constVal.GetStop().GetLine(),
   813  						Column: constVal.GetStop().GetColumn(),
   814  					},
   815  				},
   816  			}
   817  		}
   818  		msg.TypeExpr.Inst = &ts.InstExpr{
   819  			Ref: core.EntityRef{Name: "float"},
   820  		}
   821  		if constVal.MINUS() != nil {
   822  			parsedFloat = -parsedFloat
   823  		}
   824  		msg.Float = &parsedFloat
   825  	case constVal.STRING() != nil:
   826  		msg.Str = compiler.Pointer(
   827  			strings.Trim(
   828  				strings.ReplaceAll(
   829  					constVal.STRING().GetText(),
   830  					"\\n",
   831  					"\n",
   832  				),
   833  				"'",
   834  			),
   835  		)
   836  		msg.TypeExpr.Inst = &ts.InstExpr{
   837  			Ref: core.EntityRef{Name: "string"},
   838  		}
   839  	case constVal.EnumLit() != nil:
   840  		parsedEnumRef, err := parseEntityRef(constVal.EnumLit().EntityRef())
   841  		if err != nil {
   842  			return src.Message{}, err
   843  		}
   844  		msg.Enum = &src.EnumMessage{
   845  			EnumRef:    parsedEnumRef,
   846  			MemberName: constVal.EnumLit().IDENTIFIER().GetText(),
   847  		}
   848  		msg.TypeExpr = ts.Expr{
   849  			Inst: &ts.InstExpr{Ref: parsedEnumRef},
   850  			Meta: parsedEnumRef.Meta,
   851  		}
   852  	case constVal.ListLit() != nil:
   853  		listItems := constVal.ListLit().ListItems()
   854  		if listItems == nil { // empty list []
   855  			msg.List = []src.Const{}
   856  			return src.Message{}, nil
   857  		}
   858  		items := listItems.AllCompositeItem()
   859  		msg.List = make([]src.Const, 0, len(items))
   860  		for _, item := range items {
   861  			constant := src.Const{
   862  				Meta: core.Meta{
   863  					Text: item.GetText(),
   864  					Start: core.Position{
   865  						Line:   item.GetStart().GetLine(),
   866  						Column: item.GetStart().GetLine(),
   867  					},
   868  					Stop: core.Position{
   869  						Line:   item.GetStop().GetLine(),
   870  						Column: item.GetStop().GetLine(),
   871  					},
   872  				},
   873  			}
   874  			if item.EntityRef() != nil {
   875  				parsedRef, err := parseEntityRef(item.EntityRef())
   876  				if err != nil {
   877  					return src.Message{}, err
   878  				}
   879  				constant.Ref = &parsedRef
   880  			} else {
   881  				parsedConstValue, err := parseMessage(item.ConstLit())
   882  				if err != nil {
   883  					return src.Message{}, err
   884  				}
   885  				constant.Message = &parsedConstValue
   886  
   887  			}
   888  			msg.List = append(msg.List, constant)
   889  		}
   890  	case constVal.StructLit() != nil:
   891  		fields := constVal.StructLit().StructValueFields()
   892  		if fields == nil { // empty struct {}
   893  			msg.MapOrStruct = map[string]src.Const{}
   894  			return msg, nil
   895  		}
   896  		fieldValues := fields.AllStructValueField()
   897  		msg.MapOrStruct = make(map[string]src.Const, len(fieldValues))
   898  		for _, field := range fieldValues {
   899  			if field.IDENTIFIER() == nil {
   900  				panic("field.GetText()")
   901  			}
   902  			name := field.IDENTIFIER().GetText()
   903  			if field.CompositeItem().EntityRef() != nil {
   904  				parsedRef, err := parseEntityRef(field.CompositeItem().EntityRef())
   905  				if err != nil {
   906  					return src.Message{}, err
   907  				}
   908  				msg.MapOrStruct[name] = src.Const{
   909  					Ref: &parsedRef,
   910  				}
   911  			} else {
   912  				value, err := parseMessage(field.CompositeItem().ConstLit())
   913  				if err != nil {
   914  					return src.Message{}, err
   915  				}
   916  				msg.MapOrStruct[name] = src.Const{
   917  					Message: &value,
   918  				}
   919  			}
   920  		}
   921  	case constVal.Nil_() != nil:
   922  		return src.Message{}, nil
   923  	default:
   924  		panic("unknown const: " + constVal.GetText())
   925  	}
   926  
   927  	return msg, nil
   928  }
   929  
   930  func parseCompilerDirectives(actx generated.ICompilerDirectivesContext) map[src.Directive][]string {
   931  	if actx == nil {
   932  		return nil
   933  	}
   934  
   935  	directives := actx.AllCompilerDirective()
   936  	result := make(map[src.Directive][]string, len(directives))
   937  	for _, directive := range directives {
   938  		id := directive.IDENTIFIER()
   939  		if directive.CompilerDirectivesArgs() == nil {
   940  			result[src.Directive(id.GetText())] = []string{}
   941  			continue
   942  		}
   943  		args := directive.CompilerDirectivesArgs().AllCompiler_directive_arg()
   944  		ss := make([]string, 0, len(args))
   945  		for _, arg := range args {
   946  			s := ""
   947  			ids := arg.AllIDENTIFIER()
   948  			for i, id := range ids {
   949  				s += id.GetText()
   950  				if i < len(ids)-1 {
   951  					s += " "
   952  				}
   953  			}
   954  			ss = append(ss, s)
   955  		}
   956  		result[src.Directive(id.GetText())] = ss
   957  	}
   958  
   959  	return result
   960  }
   961  
   962  func parseTypeDef(
   963  	actx generated.ITypeDefContext,
   964  ) (src.Entity, *compiler.Error) {
   965  	var body *ts.Expr
   966  	if expr := actx.TypeExpr(); expr != nil {
   967  		v, err := parseTypeExpr(actx.TypeExpr())
   968  		if err != nil {
   969  			return src.Entity{}, err
   970  		}
   971  		body = compiler.Pointer(v)
   972  	}
   973  
   974  	v, err := parseTypeParams(actx.TypeParams())
   975  	if err != nil {
   976  		return src.Entity{}, err
   977  	}
   978  
   979  	return src.Entity{
   980  		Kind: src.TypeEntity,
   981  		Type: ts.Def{
   982  			Params:   v.Params,
   983  			BodyExpr: body,
   984  			// CanBeUsedForRecursiveDefinitions: body == nil,
   985  			Meta: core.Meta{
   986  				Text: actx.GetText(),
   987  				Start: core.Position{
   988  					Line:   actx.GetStart().GetLine(),
   989  					Column: actx.GetStart().GetColumn(),
   990  				},
   991  				Stop: core.Position{
   992  					Line:   actx.GetStop().GetLine(),
   993  					Column: actx.GetStop().GetColumn(),
   994  				},
   995  			},
   996  		},
   997  	}, nil
   998  }
   999  
  1000  func parseConstDef(
  1001  	actx generated.IConstDefContext,
  1002  ) (src.Entity, *compiler.Error) {
  1003  	constVal := actx.ConstLit()
  1004  	entityRef := actx.EntityRef()
  1005  
  1006  	if constVal == nil && entityRef == nil {
  1007  		panic("constVal == nil && entityRef == nil")
  1008  	}
  1009  
  1010  	meta := core.Meta{
  1011  		Text: actx.GetText(),
  1012  		Start: core.Position{
  1013  			Line:   actx.GetStart().GetLine(),
  1014  			Column: actx.GetStart().GetColumn(),
  1015  		},
  1016  		Stop: core.Position{
  1017  			Line:   actx.GetStop().GetLine(),
  1018  			Column: actx.GetStop().GetColumn(),
  1019  		},
  1020  	}
  1021  
  1022  	var parsedConst src.Const
  1023  
  1024  	if entityRef != nil {
  1025  		parsedRef, err := parseEntityRef(entityRef)
  1026  		if err != nil {
  1027  			return src.Entity{}, &compiler.Error{
  1028  				Err:  err,
  1029  				Meta: &meta,
  1030  			}
  1031  		}
  1032  		parsedConst = src.Const{
  1033  			Ref:  &parsedRef,
  1034  			Meta: meta,
  1035  		}
  1036  	} else {
  1037  		parsedMsg, err := parseMessage(constVal)
  1038  		if err != nil {
  1039  			return src.Entity{}, &compiler.Error{
  1040  				Err:  err,
  1041  				Meta: &meta,
  1042  			}
  1043  		}
  1044  		typeExpr, err := parseTypeExpr(actx.TypeExpr())
  1045  		if err != nil {
  1046  			return src.Entity{}, &compiler.Error{
  1047  				Err:  err,
  1048  				Meta: &meta,
  1049  			}
  1050  		}
  1051  		parsedMsg.TypeExpr = typeExpr
  1052  		parsedConst = src.Const{
  1053  			Message: &parsedMsg,
  1054  			Meta:    meta,
  1055  		}
  1056  	}
  1057  
  1058  	return src.Entity{
  1059  		Kind:  src.ConstEntity,
  1060  		Const: parsedConst,
  1061  	}, nil
  1062  }
  1063  
  1064  func parseCompDef(actx generated.ICompDefContext) (src.Entity, *compiler.Error) {
  1065  	parsedInterfaceDef, err := parseInterfaceDef(actx.InterfaceDef())
  1066  	if err != nil {
  1067  		return src.Entity{}, err
  1068  	}
  1069  
  1070  	body := actx.CompBody()
  1071  	if body == nil {
  1072  		return src.Entity{
  1073  			Kind: src.ComponentEntity,
  1074  			Component: src.Component{
  1075  				Interface: parsedInterfaceDef,
  1076  			},
  1077  		}, nil
  1078  	}
  1079  
  1080  	parsedConnections := []src.Connection{}
  1081  	connections := actx.CompBody().ConnDefList()
  1082  	if connections != nil {
  1083  		parsedNet, err := parseNet(connections)
  1084  		if err != nil {
  1085  			return src.Entity{}, err
  1086  		}
  1087  		parsedConnections = parsedNet
  1088  	}
  1089  
  1090  	nodesDef := body.CompNodesDef()
  1091  	if nodesDef == nil {
  1092  		return src.Entity{
  1093  			Kind: src.ComponentEntity,
  1094  			Component: src.Component{
  1095  				Interface: parsedInterfaceDef,
  1096  				Net:       parsedConnections,
  1097  			},
  1098  		}, nil
  1099  	}
  1100  
  1101  	var parsedNodes map[string]src.Node
  1102  	v, err := parseNodes(nodesDef.CompNodesDefBody(), true)
  1103  	if err != nil {
  1104  		return src.Entity{}, err
  1105  	}
  1106  	parsedNodes = v
  1107  
  1108  	return src.Entity{
  1109  		Kind: src.ComponentEntity,
  1110  		Component: src.Component{
  1111  			Interface: parsedInterfaceDef,
  1112  			Nodes:     parsedNodes,
  1113  			Net:       parsedConnections,
  1114  		},
  1115  	}, nil
  1116  }