fix: improve switch and type switch statement processing

This commit is contained in:
Marc Vertes
2020-05-03 18:20:04 +02:00
committed by GitHub
parent f6c8b8b14f
commit ff36ec58b1
4 changed files with 59 additions and 17 deletions

13
_test/switch34.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func main() {
var a interface{}
switch a.(type) {
case []int:
case []string:
}
println("bye")
}
// Output:
// bye

View File

@@ -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 {

View File

@@ -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
@@ -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

View File

@@ -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
}