2020-05-13 15:09:55 +00:00
|
|
|
package compiler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"go/ast"
|
|
|
|
"go/types"
|
2020-06-24 14:58:15 +00:00
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
2020-05-13 15:09:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func (c *codegen) typeAndValueOf(e ast.Expr) types.TypeAndValue {
|
2021-02-04 12:41:00 +00:00
|
|
|
for i := len(c.pkgInfoInline) - 1; i >= 0; i-- {
|
2021-12-02 14:44:53 +00:00
|
|
|
if tv, ok := c.pkgInfoInline[i].TypesInfo.Types[e]; ok {
|
2021-02-04 12:41:00 +00:00
|
|
|
return tv
|
|
|
|
}
|
|
|
|
}
|
2021-12-02 14:44:53 +00:00
|
|
|
|
|
|
|
if tv, ok := c.typeInfo.Types[e]; ok {
|
|
|
|
return tv
|
|
|
|
}
|
|
|
|
|
|
|
|
se, ok := e.(*ast.SelectorExpr)
|
|
|
|
if ok {
|
|
|
|
if tv, ok := c.typeInfo.Selections[se]; ok {
|
|
|
|
return types.TypeAndValue{Type: tv.Type()}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return types.TypeAndValue{}
|
2020-05-13 15:09:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *codegen) typeOf(e ast.Expr) types.Type {
|
2021-12-02 14:44:53 +00:00
|
|
|
for i := len(c.pkgInfoInline) - 1; i >= 0; i-- {
|
|
|
|
if typ := c.pkgInfoInline[i].TypesInfo.TypeOf(e); typ != nil {
|
|
|
|
return typ
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, p := range c.packageCache {
|
|
|
|
typ := p.TypesInfo.TypeOf(e)
|
|
|
|
if typ != nil {
|
|
|
|
return typ
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
2020-05-13 15:09:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func isBasicTypeOfKind(typ types.Type, ks ...types.BasicKind) bool {
|
|
|
|
if t, ok := typ.Underlying().(*types.Basic); ok {
|
|
|
|
k := t.Kind()
|
|
|
|
for i := range ks {
|
|
|
|
if k == ks[i] {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-08-24 08:58:29 +00:00
|
|
|
func isMap(typ types.Type) bool {
|
|
|
|
_, ok := typ.Underlying().(*types.Map)
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:09:55 +00:00
|
|
|
func isByte(typ types.Type) bool {
|
|
|
|
return isBasicTypeOfKind(typ, types.Uint8, types.Int8)
|
|
|
|
}
|
|
|
|
|
2020-08-23 11:52:37 +00:00
|
|
|
func isBool(typ types.Type) bool {
|
|
|
|
return isBasicTypeOfKind(typ, types.Bool, types.UntypedBool)
|
|
|
|
}
|
|
|
|
|
2020-08-23 09:39:58 +00:00
|
|
|
func isNumber(typ types.Type) bool {
|
|
|
|
t, ok := typ.Underlying().(*types.Basic)
|
|
|
|
return ok && t.Info()&types.IsNumeric != 0
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:09:55 +00:00
|
|
|
func isString(typ types.Type) bool {
|
|
|
|
return isBasicTypeOfKind(typ, types.String)
|
|
|
|
}
|
|
|
|
|
|
|
|
func isCompoundSlice(typ types.Type) bool {
|
|
|
|
t, ok := typ.Underlying().(*types.Slice)
|
|
|
|
return ok && !isByte(t.Elem())
|
|
|
|
}
|
|
|
|
|
|
|
|
func isByteSlice(typ types.Type) bool {
|
|
|
|
t, ok := typ.Underlying().(*types.Slice)
|
|
|
|
return ok && isByte(t.Elem())
|
|
|
|
}
|
2020-06-24 14:58:15 +00:00
|
|
|
|
|
|
|
func toNeoType(typ types.Type) stackitem.Type {
|
|
|
|
if typ == nil {
|
|
|
|
return stackitem.AnyT
|
|
|
|
}
|
|
|
|
switch t := typ.Underlying().(type) {
|
|
|
|
case *types.Basic:
|
|
|
|
info := t.Info()
|
|
|
|
switch {
|
|
|
|
case info&types.IsInteger != 0:
|
|
|
|
return stackitem.IntegerT
|
|
|
|
case info&types.IsBoolean != 0:
|
|
|
|
return stackitem.BooleanT
|
|
|
|
case info&types.IsString != 0:
|
|
|
|
return stackitem.ByteArrayT
|
|
|
|
default:
|
|
|
|
return stackitem.AnyT
|
|
|
|
}
|
|
|
|
case *types.Map:
|
|
|
|
return stackitem.MapT
|
|
|
|
case *types.Struct:
|
|
|
|
return stackitem.StructT
|
|
|
|
case *types.Slice:
|
|
|
|
if isByte(t.Elem()) {
|
|
|
|
return stackitem.BufferT
|
|
|
|
}
|
|
|
|
return stackitem.ArrayT
|
|
|
|
default:
|
|
|
|
return stackitem.AnyT
|
|
|
|
}
|
|
|
|
}
|