github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/compiler/types.go (about)

     1  package compiler
     2  
     3  import (
     4  	"go/ast"
     5  	"go/types"
     6  
     7  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
     8  )
     9  
    10  func (c *codegen) typeAndValueOf(e ast.Expr) types.TypeAndValue {
    11  	for i := len(c.pkgInfoInline) - 1; i >= 0; i-- {
    12  		if tv, ok := c.pkgInfoInline[i].TypesInfo.Types[e]; ok {
    13  			return tv
    14  		}
    15  	}
    16  
    17  	if tv, ok := c.typeInfo.Types[e]; ok {
    18  		return tv
    19  	}
    20  
    21  	se, ok := e.(*ast.SelectorExpr)
    22  	if ok {
    23  		if tv, ok := c.typeInfo.Selections[se]; ok {
    24  			return types.TypeAndValue{Type: tv.Type()}
    25  		}
    26  	}
    27  	return types.TypeAndValue{}
    28  }
    29  
    30  func (c *codegen) typeOf(e ast.Expr) types.Type {
    31  	for i := len(c.pkgInfoInline) - 1; i >= 0; i-- {
    32  		if typ := c.pkgInfoInline[i].TypesInfo.TypeOf(e); typ != nil {
    33  			return typ
    34  		}
    35  	}
    36  	for _, p := range c.packageCache {
    37  		typ := p.TypesInfo.TypeOf(e)
    38  		if typ != nil {
    39  			return typ
    40  		}
    41  	}
    42  	return nil
    43  }
    44  
    45  func isBasicTypeOfKind(typ types.Type, ks ...types.BasicKind) bool {
    46  	if t, ok := typ.Underlying().(*types.Basic); ok {
    47  		k := t.Kind()
    48  		for i := range ks {
    49  			if k == ks[i] {
    50  				return true
    51  			}
    52  		}
    53  	}
    54  	return false
    55  }
    56  
    57  func isMap(typ types.Type) bool {
    58  	_, ok := typ.Underlying().(*types.Map)
    59  	return ok
    60  }
    61  
    62  func isByte(typ types.Type) bool {
    63  	return isBasicTypeOfKind(typ, types.Uint8, types.Int8)
    64  }
    65  
    66  func isBool(typ types.Type) bool {
    67  	return isBasicTypeOfKind(typ, types.Bool, types.UntypedBool)
    68  }
    69  
    70  func isNumber(typ types.Type) bool {
    71  	t, ok := typ.Underlying().(*types.Basic)
    72  	return ok && t.Info()&types.IsNumeric != 0
    73  }
    74  
    75  func isString(typ types.Type) bool {
    76  	return isBasicTypeOfKind(typ, types.String)
    77  }
    78  
    79  func isCompoundSlice(typ types.Type) bool {
    80  	t, ok := typ.Underlying().(*types.Slice)
    81  	return ok && !isByte(t.Elem())
    82  }
    83  
    84  func isByteSlice(typ types.Type) bool {
    85  	t, ok := typ.Underlying().(*types.Slice)
    86  	return ok && isByte(t.Elem())
    87  }
    88  
    89  func toNeoType(typ types.Type) stackitem.Type {
    90  	if typ == nil {
    91  		return stackitem.AnyT
    92  	}
    93  	switch t := typ.Underlying().(type) {
    94  	case *types.Basic:
    95  		info := t.Info()
    96  		switch {
    97  		case info&types.IsInteger != 0:
    98  			return stackitem.IntegerT
    99  		case info&types.IsBoolean != 0:
   100  			return stackitem.BooleanT
   101  		case info&types.IsString != 0:
   102  			return stackitem.ByteArrayT
   103  		default:
   104  			return stackitem.AnyT
   105  		}
   106  	case *types.Map:
   107  		return stackitem.MapT
   108  	case *types.Struct:
   109  		return stackitem.StructT
   110  	case *types.Slice:
   111  		if isByte(t.Elem()) {
   112  			return stackitem.BufferT
   113  		}
   114  		return stackitem.ArrayT
   115  	default:
   116  		return stackitem.AnyT
   117  	}
   118  }