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

     1  package irgen
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/nevalang/neva/internal/compiler"
     7  	src "github.com/nevalang/neva/internal/compiler/sourcecode"
     8  	"github.com/nevalang/neva/internal/runtime/ir"
     9  )
    10  
    11  func getIRMsgBySrcRef(constant src.Const, scope src.Scope) (*ir.Msg, *compiler.Error) { //nolint:funlen
    12  	if constant.Ref != nil {
    13  		entity, location, err := scope.Entity(*constant.Ref)
    14  		if err != nil {
    15  			return nil, &compiler.Error{
    16  				Err:      err,
    17  				Location: &scope.Location,
    18  			}
    19  		}
    20  		return getIRMsgBySrcRef(entity.Const, scope.WithLocation(location))
    21  	}
    22  
    23  	switch {
    24  	case constant.Message.Bool != nil:
    25  		return &ir.Msg{
    26  			Type: ir.MsgTypeBool,
    27  			Bool: *constant.Message.Bool,
    28  		}, nil
    29  	case constant.Message.Int != nil:
    30  		return &ir.Msg{
    31  			Type: ir.MsgTypeInt,
    32  			Int:  int64(*constant.Message.Int),
    33  		}, nil
    34  	case constant.Message.Float != nil:
    35  		return &ir.Msg{
    36  			Type:  ir.MsgTypeFloat,
    37  			Float: *constant.Message.Float,
    38  		}, nil
    39  	case constant.Message.Str != nil:
    40  		return &ir.Msg{
    41  			Type: ir.MsgTypeString,
    42  			Str:  *constant.Message.Str,
    43  		}, nil
    44  	case constant.Message.Enum != nil:
    45  		enumTypeExpr := constant.Message.TypeExpr.Lit.Enum
    46  		return &ir.Msg{
    47  			Type: ir.MsgTypeInt,
    48  			Int:  int64(getEnumMemberIndex(enumTypeExpr, constant.Message.Enum.MemberName)),
    49  		}, nil
    50  	case constant.Message.List != nil:
    51  		listMsg := make([]ir.Msg, len(constant.Message.List))
    52  
    53  		for i, el := range constant.Message.List {
    54  			result, err := getIRMsgBySrcRef(el, scope)
    55  			if err != nil {
    56  				return nil, err
    57  			}
    58  			listMsg[i] = *result
    59  		}
    60  
    61  		return &ir.Msg{
    62  			Type: ir.MsgTypeList,
    63  			List: listMsg,
    64  		}, nil
    65  	case constant.Message.MapOrStruct != nil:
    66  		mapMsg := make(map[string]ir.Msg, len(constant.Message.MapOrStruct))
    67  
    68  		for name, el := range constant.Message.MapOrStruct {
    69  			result, err := getIRMsgBySrcRef(el, scope)
    70  			if err != nil {
    71  				return nil, err
    72  			}
    73  			mapMsg[name] = *result // see Q&A on why we don't create flat maps for nested structures
    74  		}
    75  
    76  		return &ir.Msg{
    77  			Type: ir.MsgTypeMap,
    78  			Map:  mapMsg,
    79  		}, nil
    80  	}
    81  
    82  	return nil, &compiler.Error{
    83  		Err:      errors.New("unknown msg type"),
    84  		Location: &scope.Location,
    85  	}
    86  }
    87  
    88  func getEnumMemberIndex(enum []string, value string) int {
    89  	for i, item := range enum {
    90  		if item == value {
    91  			return i
    92  		}
    93  	}
    94  	return -1
    95  }