Skip to content

Commit

Permalink
fix: improve switch and type switch statement processing
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes committed May 3, 2020
1 parent f6c8b8b commit ff36ec5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 17 deletions.
13 changes: 13 additions & 0 deletions _test/switch34.go
@@ -0,0 +1,13 @@
package main

func main() {
var a interface{}
switch a.(type) {
case []int:
case []string:
}
println("bye")
}

// Output:
// bye
1 change: 1 addition & 0 deletions interp/cfg.go
Expand Up @@ -1467,6 +1467,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
}
}
c := clauses[l-1] // Last clause.
c.fnext = n
if len(c.child) == 0 {
c.tnext = n // Clause body is empty, exit.
} else {
Expand Down
20 changes: 11 additions & 9 deletions interp/run.go
Expand Up @@ -2059,11 +2059,12 @@ func _case(n *node) {
// match against multiple types: assign var to interface value
n.exec = func(f *frame) bltn {
val := srcValue(f)
vid := val.Interface().(valueInterface).node.typ.id()
for _, typ := range types {
if vid == typ.id() {
destValue(f).Set(val)
return tnext
if v := srcValue(f).Interface().(valueInterface).node; v != nil {
for _, typ := range types {
if v.typ.id() == typ.id() {
destValue(f).Set(val)
return tnext
}
}
}
return fnext
Expand All @@ -2075,10 +2076,11 @@ func _case(n *node) {
n.exec = func(f *frame) bltn { return tnext }
} else {
n.exec = func(f *frame) bltn {
vtyp := srcValue(f).Interface().(valueInterface).node.typ
for _, typ := range types {
if vtyp.id() == typ.id() {
return tnext
if v := srcValue(f).Interface().(valueInterface).node; v != nil {
for _, typ := range types {
if v.typ.id() == typ.id() {
return tnext
}
}
}
return fnext
Expand Down
42 changes: 34 additions & 8 deletions interp/type.go
Expand Up @@ -845,17 +845,43 @@ func (t *itype) methods() methodSet {
}

// id returns a unique type identificator string
func (t *itype) id() string {
// TODO: if res is nil, build identity from String()

res := ""
func (t *itype) id() (res string) {
if t.name != "" {
return t.path + "." + t.name
}
switch t.cat {
case valueT:
res = t.rtype.PkgPath() + "." + t.rtype.Name()
case arrayT:
res = "[" + strconv.Itoa(t.size) + "]" + t.val.id()
case chanT:
res = "<-" + t.val.id()
case funcT:
res = "func("
for _, t := range t.arg {
res += t.id() + ","
}
res += ")("
for _, t := range t.ret {
res += t.id() + ","
}
res += ")"
case interfaceT:
res = "interface{"
for _, t := range t.field {
res += t.name + " " + t.typ.id() + ";"
}
res += "}"
case mapT:
res = "map[" + t.key.id() + "]" + t.val.id()
case ptrT:
res = "*" + t.val.id()
default:
res = t.path + "." + t.name
case structT:
res = "struct{"
for _, t := range t.field {
res += t.name + " " + t.typ.id() + ";"
}
res += "}"
case valueT:
res = t.rtype.PkgPath() + "." + t.rtype.Name()
}
return res
}
Expand Down

0 comments on commit ff36ec5

Please sign in to comment.