Skip to content

Commit

Permalink
fix: range over string iterates on runes instead of bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored and traefiker committed Sep 23, 2019
1 parent 030dd3c commit 8a88a1a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
19 changes: 19 additions & 0 deletions _test/for6.go
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()}
Expand All @@ -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
Expand Down
19 changes: 16 additions & 3 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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]
Expand Down

0 comments on commit 8a88a1a

Please sign in to comment.