mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 13:41:47 +00:00
compiler: allow conversion to types from external packages
This commit is contained in:
parent
1f98289f5d
commit
e5d8c1c985
3 changed files with 68 additions and 5 deletions
|
@ -821,13 +821,20 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
f, ok = c.funcs[name]
|
f, ok = c.funcs[name]
|
||||||
// @FIXME this could cause runtime errors.
|
if ok {
|
||||||
f.selector = fun.X.(*ast.Ident)
|
f.selector = fun.X.(*ast.Ident)
|
||||||
if !ok {
|
isBuiltin = isCustomBuiltin(f)
|
||||||
c.prog.Err = fmt.Errorf("could not resolve function %s", fun.Sel.Name)
|
} else {
|
||||||
|
typ := c.typeOf(fun)
|
||||||
|
if _, ok := typ.(*types.Signature); ok {
|
||||||
|
c.prog.Err = fmt.Errorf("could not resolve function %s", fun.Sel.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ast.Walk(c, n.Args[0])
|
||||||
|
c.emitExplicitConvert(c.typeOf(n.Args[0]), typ)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
isBuiltin = isCustomBuiltin(f)
|
|
||||||
case *ast.ArrayType:
|
case *ast.ArrayType:
|
||||||
// For now we will assume that there are only byte slice conversions.
|
// For now we will assume that there are only byte slice conversions.
|
||||||
// E.g. []byte("foobar") or []byte(scriptHash).
|
// E.g. []byte("foobar") or []byte(scriptHash).
|
||||||
|
@ -1242,6 +1249,24 @@ func (c *codegen) processDefers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emitExplicitConvert handles `someType(someValue)` conversions between string/[]byte.
|
||||||
|
// Rules for conversion:
|
||||||
|
// 1. interop.* types are converted to ByteArray if not already.
|
||||||
|
// 2. Otherwise convert between ByteArray/Buffer.
|
||||||
|
// 3. Rules for types which are not string/[]byte should already
|
||||||
|
// be enforced by go parser.
|
||||||
|
func (c *codegen) emitExplicitConvert(from, to types.Type) {
|
||||||
|
if isInteropPath(to.String()) {
|
||||||
|
if isByteSlice(from) && !isString(from) {
|
||||||
|
c.emitConvert(stackitem.ByteArrayT)
|
||||||
|
}
|
||||||
|
} else if isByteSlice(to) && !isByteSlice(from) {
|
||||||
|
c.emitConvert(stackitem.BufferT)
|
||||||
|
} else if isString(to) && !isString(from) {
|
||||||
|
c.emitConvert(stackitem.ByteArrayT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *codegen) rangeLoadKey() {
|
func (c *codegen) rangeLoadKey() {
|
||||||
emit.Int(c.prog.BinWriter, 2)
|
emit.Int(c.prog.BinWriter, 2)
|
||||||
emit.Opcodes(c.prog.BinWriter,
|
emit.Opcodes(c.prog.BinWriter,
|
||||||
|
|
|
@ -87,6 +87,37 @@ func TestTypeConversion(t *testing.T) {
|
||||||
eval(t, src, big.NewInt(42))
|
eval(t, src, big.NewInt(42))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSelectorTypeConversion(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/types"
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
|
func Main() int {
|
||||||
|
var a int
|
||||||
|
if util.Equals(types.Buffer(nil), nil) {
|
||||||
|
a += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer != ByteArray
|
||||||
|
if util.Equals(types.Buffer("\x12"), "\x12") {
|
||||||
|
a += 10
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := []byte{0x23}
|
||||||
|
if util.Equals(types.ByteString(tmp), "\x23") {
|
||||||
|
a += 100
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := "aaaaaaaaaaaaaaaaaaaa"
|
||||||
|
buf := []byte(addr)
|
||||||
|
if util.Equals(interop.Hash160(addr), interop.Hash160(buf)) {
|
||||||
|
a += 1000
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(1101))
|
||||||
|
}
|
||||||
|
|
||||||
func TestTypeConversionString(t *testing.T) {
|
func TestTypeConversionString(t *testing.T) {
|
||||||
src := `package foo
|
src := `package foo
|
||||||
type mystr string
|
type mystr string
|
||||||
|
|
7
pkg/compiler/testdata/types/types.go
vendored
Normal file
7
pkg/compiler/testdata/types/types.go
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
// Buffer represents Buffer VM type.
|
||||||
|
type Buffer []byte
|
||||||
|
|
||||||
|
// ByteString represents ByteString VM type.
|
||||||
|
type ByteString string
|
Loading…
Reference in a new issue