compiler: allow conversion to types from external packages

This commit is contained in:
Evgeniy Stratonikov 2021-02-03 16:10:31 +03:00
parent 1f98289f5d
commit e5d8c1c985
3 changed files with 68 additions and 5 deletions

View file

@ -821,13 +821,20 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
}
f, ok = c.funcs[name]
// @FIXME this could cause runtime errors.
f.selector = fun.X.(*ast.Ident)
if !ok {
c.prog.Err = fmt.Errorf("could not resolve function %s", fun.Sel.Name)
if ok {
f.selector = fun.X.(*ast.Ident)
isBuiltin = isCustomBuiltin(f)
} 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
}
isBuiltin = isCustomBuiltin(f)
case *ast.ArrayType:
// For now we will assume that there are only byte slice conversions.
// 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() {
emit.Int(c.prog.BinWriter, 2)
emit.Opcodes(c.prog.BinWriter,