diff --git a/_test/interface20.go b/_test/interface20.go new file mode 100644 index 00000000..c3a9f396 --- /dev/null +++ b/_test/interface20.go @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + var a interface{} + a = string("A") + fmt.Println(a) +} + +// Output: +// A diff --git a/_test/interface21.go b/_test/interface21.go new file mode 100644 index 00000000..57f7a58e --- /dev/null +++ b/_test/interface21.go @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + s := make([]interface{}, 1) + s[0] = 1 + fmt.Println(s[0]) +} + +// Output: +// 1 diff --git a/_test/interface22.go b/_test/interface22.go new file mode 100644 index 00000000..7ba88efe --- /dev/null +++ b/_test/interface22.go @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + s := make([]interface{}, 0) + s = append(s, 1) + fmt.Println(s[0]) +} + +// Output: +// 1 diff --git a/_test/interface23.go b/_test/interface23.go new file mode 100644 index 00000000..fe02f20a --- /dev/null +++ b/_test/interface23.go @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + m := make(map[string]interface{}) + m["A"] = string("A") + fmt.Println(m["A"]) +} + +// Output: +// A diff --git a/_test/interface24.go b/_test/interface24.go new file mode 100644 index 00000000..0ed7e12c --- /dev/null +++ b/_test/interface24.go @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + m := make(map[string]interface{}) + fmt.Println(m["B"]) +} + +// Output: +// diff --git a/_test/interface25.go b/_test/interface25.go new file mode 100644 index 00000000..cdc6e86e --- /dev/null +++ b/_test/interface25.go @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + m := make(map[string]interface{}) + m["A"] = 1 + for _, v := range m { + fmt.Println(v) + } +} + +// Output: +// 1 diff --git a/_test/interface26.go b/_test/interface26.go new file mode 100644 index 00000000..e1cec9df --- /dev/null +++ b/_test/interface26.go @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + s := make([]interface{}, 0) + s = append(s, 1) + for _, v := range s { + fmt.Println(v) + } +} + +// Output: +// 1 diff --git a/interp/cfg.go b/interp/cfg.go index 90efd337..26ea3462 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -464,7 +464,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) { err = n.cfgErrorf("illegal operand types for '%v' operator", n.action) } default: - // Detect invalid float truncate + // Detect invalid float truncate. if isInt(t0) && isFloat(t1) { err = src.cfgErrorf("invalid float truncate") return @@ -475,7 +475,8 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) { // Propagate type // TODO: Check that existing destination type matches source type switch { - case n.action == aAssign && src.action == aCall: + case n.action == aAssign && src.action == aCall && dest.typ.cat != interfaceT: + // Call action may perform the assignment directly. n.gen = nop src.level = level src.findex = dest.findex @@ -483,7 +484,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) { src.typ = dest.typ } case n.action == aAssign && src.action == aRecv: - // Assign by reading from a receiving channel + // Assign by reading from a receiving channel. n.gen = nop src.findex = dest.findex // Set recv address to LHS dest.typ = src.typ @@ -492,16 +493,16 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) { src.findex = dest.findex src.level = level case src.kind == basicLit: - // TODO: perform constant folding and propagation here + // TODO: perform constant folding and propagation here. switch { case dest.typ.cat == interfaceT: case isComplex(dest.typ.TypeOf()): - // value set in genValue + // Value set in genValue. case !src.rval.IsValid(): - // Assign to nil + // Assign to nil. src.rval = reflect.New(dest.typ.TypeOf()).Elem() default: - // Convert literal value to destination type + // Convert literal value to destination type. src.rval = src.rval.Convert(dest.typ.TypeOf()) src.typ = dest.typ } diff --git a/interp/run.go b/interp/run.go index 375830e7..8846b811 100644 --- a/interp/run.go +++ b/interp/run.go @@ -1025,12 +1025,13 @@ func getIndexMap(n *node) { dest := genValue(n) value0 := genValue(n.child[0]) // map tnext := getExec(n.tnext) - z := reflect.New(n.child[0].typ.TypeOf().Elem()).Elem() + z := reflect.New(n.child[0].typ.frameType().Elem()).Elem() if n.child[1].rval.IsValid() { // constant map index mi := n.child[1].rval - if n.fnext != nil { + switch { + case n.fnext != nil: fnext := getExec(n.fnext) n.exec = func(f *frame) bltn { if v := value0(f).MapIndex(mi); v.IsValid() && v.Bool() { @@ -1040,7 +1041,17 @@ func getIndexMap(n *node) { dest(f).Set(z) return fnext } - } else { + case n.typ.cat == interfaceT: + z = reflect.New(n.child[0].typ.val.frameType()).Elem() + n.exec = func(f *frame) bltn { + if v := value0(f).MapIndex(mi); v.IsValid() { + dest(f).Set(v.Elem()) + } else { + dest(f).Set(z) + } + return tnext + } + default: n.exec = func(f *frame) bltn { if v := value0(f).MapIndex(mi); v.IsValid() { dest(f).Set(v) @@ -1053,7 +1064,8 @@ func getIndexMap(n *node) { } else { value1 := genValue(n.child[1]) // map index - if n.fnext != nil { + switch { + case n.fnext != nil: fnext := getExec(n.fnext) n.exec = func(f *frame) bltn { if v := value0(f).MapIndex(value1(f)); v.IsValid() && v.Bool() { @@ -1063,7 +1075,17 @@ func getIndexMap(n *node) { dest(f).Set(z) return fnext } - } else { + case n.typ.cat == interfaceT: + z = reflect.New(n.child[0].typ.val.frameType()).Elem() + n.exec = func(f *frame) bltn { + if v := value0(f).MapIndex(value1(f)); v.IsValid() { + dest(f).Set(v.Elem()) + } else { + dest(f).Set(z) + } + return tnext + } + default: n.exec = func(f *frame) bltn { if v := value0(f).MapIndex(value1(f)); v.IsValid() { dest(f).Set(v) @@ -1082,26 +1104,49 @@ func getIndexMap2(n *node) { value0 := genValue(n.child[0]) // map value2 := genValue(n.anc.child[1]) // status next := getExec(n.tnext) + typ := n.anc.child[0].typ if n.child[1].rval.IsValid() { // constant map index mi := n.child[1].rval - n.exec = func(f *frame) bltn { - v := value0(f).MapIndex(mi) - if v.IsValid() { - dest(f).Set(v) + if typ.cat == interfaceT { + n.exec = func(f *frame) bltn { + v := value0(f).MapIndex(mi) + if v.IsValid() { + dest(f).Set(v.Elem()) + } + value2(f).SetBool(v.IsValid()) + return next + } + } else { + n.exec = func(f *frame) bltn { + v := value0(f).MapIndex(mi) + if v.IsValid() { + dest(f).Set(v) + } + value2(f).SetBool(v.IsValid()) + return next } - value2(f).SetBool(v.IsValid()) - return next } } else { value1 := genValue(n.child[1]) // map index - n.exec = func(f *frame) bltn { - v := value0(f).MapIndex(value1(f)) - if v.IsValid() { - dest(f).Set(v) + if typ.cat == interfaceT { + n.exec = func(f *frame) bltn { + v := value0(f).MapIndex(value1(f)) + if v.IsValid() { + dest(f).Set(v.Elem()) + } + value2(f).SetBool(v.IsValid()) + return next + } + } else { + n.exec = func(f *frame) bltn { + v := value0(f).MapIndex(value1(f)) + if v.IsValid() { + dest(f).Set(v) + } + value2(f).SetBool(v.IsValid()) + return next } - value2(f).SetBool(v.IsValid()) - return next } } } @@ -1785,14 +1830,26 @@ func rangeMap(n *node) { if len(n.child) == 4 { index1 := n.child[1].findex // map value location in frame value = genValue(n.child[2]) // map - n.exec = func(f *frame) bltn { - iter := f.data[index2].Interface().(*reflect.MapIter) - if !iter.Next() { - return fnext + if n.child[1].typ.cat == interfaceT { + n.exec = func(f *frame) bltn { + iter := f.data[index2].Interface().(*reflect.MapIter) + if !iter.Next() { + return fnext + } + f.data[index0].Set(iter.Key()) + f.data[index1].Set(iter.Value().Elem()) + return tnext + } + } else { + n.exec = func(f *frame) bltn { + iter := f.data[index2].Interface().(*reflect.MapIter) + if !iter.Next() { + return fnext + } + f.data[index0].Set(iter.Key()) + f.data[index1].Set(iter.Value()) + return tnext } - f.data[index0].Set(iter.Key()) - f.data[index1].Set(iter.Value()) - return tnext } } else { value = genValue(n.child[1]) // map @@ -1960,6 +2017,8 @@ func _append(n *node) { values := make([]func(*frame) reflect.Value, l) for i, arg := range args { switch { + case n.typ.val.cat == interfaceT: + values[i] = genValueInterface(arg) case isRecursiveStruct(n.typ.val, n.typ.val.rtype): values[i] = genValueInterfacePtr(arg) case arg.typ.untyped: @@ -1980,6 +2039,8 @@ func _append(n *node) { } else { var value0 func(*frame) reflect.Value switch { + case n.typ.val.cat == interfaceT: + value0 = genValueInterface(n.child[2]) case isRecursiveStruct(n.typ.val, n.typ.val.rtype): value0 = genValueInterfacePtr(n.child[2]) case n.child[2].typ.untyped: @@ -2113,7 +2174,7 @@ func _new(n *node) { func _make(n *node) { dest := genValue(n) next := getExec(n.tnext) - typ := n.child[1].typ.TypeOf() + typ := n.child[1].typ.frameType() switch typ.Kind() { case reflect.Array, reflect.Slice: