fix: handle append a string to a byte array (#133)

This commit is contained in:
Marc Vertes
2019-03-22 10:27:02 +01:00
committed by Ludovic Fernandez
parent 3616fb1b82
commit e766c272ed
4 changed files with 30 additions and 8 deletions

View File

@@ -581,11 +581,15 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
n.child[0].typ = &Type{cat: BuiltinT}
switch n.child[0].ident {
case "append":
if n.typ = scope.getType(n.child[1].ident); n.typ == nil {
n.typ, err = nodeType(interp, scope, n.child[1])
c1, c2 := n.child[1], n.child[2]
if n.typ = scope.getType(c1.ident); n.typ == nil {
n.typ, err = nodeType(interp, scope, c1)
}
if c2 := n.child[2]; len(n.child) == 3 && c2.typ.cat == ArrayT && c2.typ.val.id() == n.typ.val.id() {
n.gen = appendSlice
if len(n.child) == 3 {
if c2.typ.cat == ArrayT && c2.typ.val.id() == n.typ.val.id() ||
isByteArray(c1.typ) && isString(c2.typ) {
n.gen = appendSlice
}
}
case "cap", "copy", "len":
n.typ = scope.getType("int")

View File

@@ -61,6 +61,9 @@ func TestEvalBuiltin(t *testing.T) {
{src: `a := []int{}; a = append(a, 1); a`, res: "[1]"},
{src: `a := []int{1}; a = append(a, 2, 3); a`, res: "[1 2 3]"},
{src: `a := []int{1}; b := []int{2, 3}; a = append(a, b...); a`, res: "[1 2 3]"},
{src: `string(append([]byte("hello "), "world"...))`, res: "hello world"},
{src: `a := "world"; string(append([]byte("hello "), a...))`, res: "hello world"},
{src: `a := []byte("Hello"); copy(a, "world"); string(a)`, res: "world"},
})
}

View File

@@ -1308,14 +1308,23 @@ func _case(n *Node) {
func appendSlice(n *Node) {
i := n.findex
value := genValue(n.child[1])
next := getExec(n.tnext)
value := genValue(n.child[1])
value0 := genValue(n.child[2])
n.exec = func(f *Frame) Builtin {
f.data[i] = reflect.AppendSlice(value(f), value0(f))
return next
if isString(n.child[2].typ) {
typ := reflect.TypeOf([]byte{})
n.exec = func(f *Frame) Builtin {
f.data[i] = reflect.AppendSlice(value(f), value0(f).Convert(typ))
return next
}
} else {
n.exec = func(f *Frame) Builtin {
f.data[i] = reflect.AppendSlice(value(f), value0(f))
return next
}
}
}
func _append(n *Node) {

View File

@@ -580,6 +580,12 @@ func isFloat(t *Type) bool {
return false
}
func isByteArray(t *Type) bool {
r := t.TypeOf()
k := r.Kind()
return (k == reflect.Array || k == reflect.Slice) && r.Elem().Kind() == reflect.Uint8
}
func isFloat32(t *Type) bool { return t.TypeOf().Kind() == reflect.Float32 }
func isFloat64(t *Type) bool { return t.TypeOf().Kind() == reflect.Float64 }
func isUntypedNumber(t *Type) bool { return t.untyped && (isInt(t) || isFloat(t)) }