fix: improve switch and type switch statement processing
This commit is contained in:
13
_test/switch34.go
Normal file
13
_test/switch34.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
var a interface{}
|
||||
switch a.(type) {
|
||||
case []int:
|
||||
case []string:
|
||||
}
|
||||
println("bye")
|
||||
}
|
||||
|
||||
// Output:
|
||||
// bye
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user