fix: range over string iterates on runes instead of bytes

This commit is contained in:
Marc Vertes
2019-09-23 17:02:04 +02:00
committed by Traefiker Bot
parent 030dd3cbc2
commit 8a88a1ab8a
3 changed files with 37 additions and 5 deletions

19
_test/for6.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import "fmt"
func main() {
s := "三"
for i := 0; i < len(s); i++ {
fmt.Printf("byte %d: %d\n", i, s[i])
}
for i, r := range s {
fmt.Printf("rune %d: %d\n", i, r)
}
}
// Output:
// byte 0: 228
// byte 1: 184
// byte 2: 137
// rune 0: 19977

View File

@@ -77,7 +77,7 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
vtyp = &itype{cat: valueT, rtype: typ.Elem()}
case reflect.String:
ktyp = sc.getType("int")
vtyp = sc.getType("byte")
vtyp = sc.getType("rune")
case reflect.Array, reflect.Slice:
ktyp = sc.getType("int")
vtyp = &itype{cat: valueT, rtype: typ.Elem()}
@@ -96,7 +96,7 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
}
case stringT:
ktyp = sc.getType("int")
vtyp = sc.getType("byte")
vtyp = sc.getType("rune")
case arrayT, variadicT:
ktyp = sc.getType("int")
vtyp = o.typ.val

View File

@@ -1524,14 +1524,22 @@ func compositeSparse(n *node) {
func empty(n *node) {}
var rat = reflect.ValueOf((*[]rune)(nil)).Type().Elem() // runes array type
func _range(n *node) {
index0 := n.child[0].findex // array index location in frame
fnext := getExec(n.fnext)
tnext := getExec(n.tnext)
var value func(*frame) reflect.Value
if len(n.child) == 4 {
index1 := n.child[1].findex // array value location in frame
value := genValueArray(n.child[2]) // array
an := n.child[2]
index1 := n.child[1].findex // array value location in frame
if isString(an.typ.TypeOf()) {
value = genValueAs(an, rat) // range on string iterates over runes
} else {
value = genValueArray(an)
}
n.exec = func(f *frame) bltn {
a := value(f)
v0 := f.data[index0]
@@ -1544,7 +1552,12 @@ func _range(n *node) {
return tnext
}
} else {
value := genValueArray(n.child[1]) // array
an := n.child[1]
if isString(an.typ.TypeOf()) {
value = genValueAs(an, rat) // range on string iterates over runes
} else {
value = genValueArray(an)
}
n.exec = func(f *frame) bltn {
a := value(f)
v0 := f.data[index0]