-
Notifications
You must be signed in to change notification settings - Fork 77
/
types.go
118 lines (103 loc) · 2.37 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package compiler
import (
"go/ast"
"go/types"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
func (c *codegen) typeAndValueOf(e ast.Expr) types.TypeAndValue {
for i := len(c.pkgInfoInline) - 1; i >= 0; i-- {
if tv, ok := c.pkgInfoInline[i].TypesInfo.Types[e]; ok {
return tv
}
}
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{}
}
func (c *codegen) typeOf(e ast.Expr) types.Type {
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
}
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
}
func isMap(typ types.Type) bool {
_, ok := typ.Underlying().(*types.Map)
return ok
}
func isByte(typ types.Type) bool {
return isBasicTypeOfKind(typ, types.Uint8, types.Int8)
}
func isBool(typ types.Type) bool {
return isBasicTypeOfKind(typ, types.Bool, types.UntypedBool)
}
func isNumber(typ types.Type) bool {
t, ok := typ.Underlying().(*types.Basic)
return ok && t.Info()&types.IsNumeric != 0
}
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())
}
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
}
}