1
0
mirror of https://github.com/golang/go synced 2024-11-19 00:44:40 -07:00

go.tools/ssa: clarify spec of (*builder).complit().

Added test for []*map composite literals containing nested
literal subelements.  This required implementing
(reflect.Value).Map{Keys,Index} in ssa/interp.

Plus two minor fixes in ssa/interp.

R=gri
CC=golang-dev
https://golang.org/cl/20470043
This commit is contained in:
Alan Donovan 2013-10-31 17:59:52 -04:00
parent fb0632eb7d
commit 74b761d099
6 changed files with 76 additions and 16 deletions

View File

@ -386,7 +386,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
v = fn.addLocal(t, e.Lbrace)
}
v.Comment = "complit"
b.compLit(fn, v, e, t) // initialize in place
b.compLit(fn, v, e) // initialize in place
return &address{addr: v, expr: e}
case *ast.ParenExpr:
@ -470,14 +470,13 @@ func (b *builder) exprInPlace(fn *Function, loc lvalue, e ast.Expr) {
}
if _, ok := loc.(*address); ok {
typ := loc.typ()
if _, ok := typ.Underlying().(*types.Interface); ok {
if _, ok := loc.typ().Underlying().(*types.Interface); ok {
// e.g. var x interface{} = T{...}
// Can't in-place initialize an interface value.
// Fall back to copying.
} else {
addr := loc.address(fn)
b.compLit(fn, addr, e, typ) // in place
b.compLit(fn, addr, e) // in place
emitDebugRef(fn, e, addr, true)
return
}
@ -1184,10 +1183,13 @@ func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 {
// Nested composite literals are recursively initialized in place
// where possible.
//
func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ types.Type) {
// TODO(adonovan): document how and why typ ever differs from
// fn.Pkg.typeOf(e).
// A CompositeLit may have pointer type only in the recursive (nested)
// case when the type name is implicit. e.g. in []*T{{}}, the inner
// literal has type *T behaves like &T{}.
// In that case, addr must hold a T, not a *T.
//
func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit) {
typ := deref(fn.Pkg.typeOf(e))
switch t := typ.Underlying().(type) {
case *types.Struct:
for i, e := range e.Elts {
@ -1250,7 +1252,7 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ
if t != at { // slice
s := &Slice{X: array}
s.setPos(e.Lbrace)
s.setType(t)
s.setType(typ)
emitStore(fn, addr, fn.emit(s))
}
@ -1270,12 +1272,6 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ
b.exprInPlace(fn, loc, e.Value)
}
case *types.Pointer:
// Pointers can only occur in the recursive case; we
// strip them off in addr() before calling compLit
// again, so that we allocate space for a T not a *T.
panic("compLit(fn, addr, e, *types.Pointer")
default:
panic("unexpected CompositeLit type: " + t.String())
}

View File

@ -42,6 +42,8 @@ var externals = map[string]externalFn{
"(reflect.Value).IsValid": ext۰reflect۰Value۰IsValid,
"(reflect.Value).Kind": ext۰reflect۰Value۰Kind,
"(reflect.Value).Len": ext۰reflect۰Value۰Len,
"(reflect.Value).MapIndex": ext۰reflect۰Value۰MapIndex,
"(reflect.Value).MapKeys": ext۰reflect۰Value۰MapKeys,
"(reflect.Value).NumField": ext۰reflect۰Value۰NumField,
"(reflect.Value).NumMethod": ext۰reflect۰Value۰NumMethod,
"(reflect.Value).Pointer": ext۰reflect۰Value۰Pointer,

View File

@ -546,6 +546,9 @@ func runFrame(fr *frame) {
}
fr.panicking = true
fr.panic = recover()
if fr.i.mode&EnableTracing != 0 {
fmt.Fprintf(os.Stderr, "Panicking: %s.\n", fr.panic)
}
fr.runDefers()
fr.block = fr.fn.Recover // recovered panic
}()

View File

@ -306,6 +306,50 @@ func ext۰reflect۰Value۰Len(fn *ssa.Function, args []value) value {
return nil // unreachable
}
func ext۰reflect۰Value۰MapIndex(fn *ssa.Function, args []value) value {
// Signature: func (reflect.Value) Value
tValue := rV2T(args[0]).t.Underlying().(*types.Map).Key()
k := rV2V(args[1])
switch m := rV2V(args[0]).(type) {
case map[value]value:
if v, ok := m[k]; ok {
return makeReflectValue(tValue, v)
}
case *hashmap:
if v := m.lookup(k.(hashable)); v != nil {
return makeReflectValue(tValue, v)
}
default:
panic(fmt.Sprintf("(reflect.Value).MapIndex(%T, %T)", m, k))
}
return makeReflectValue(nil, nil)
}
func ext۰reflect۰Value۰MapKeys(fn *ssa.Function, args []value) value {
// Signature: func (reflect.Value) []Value
var keys []value
tKey := rV2T(args[0]).t.Underlying().(*types.Map).Key()
switch v := rV2V(args[0]).(type) {
case map[value]value:
for k := range v {
keys = append(keys, makeReflectValue(tKey, k))
}
case *hashmap:
for _, e := range v.table {
for ; e != nil; e = e.next {
keys = append(keys, makeReflectValue(tKey, e.key))
}
}
default:
panic(fmt.Sprintf("(reflect.Value).MapKeys(%T)", v))
}
return keys
}
func ext۰reflect۰Value۰NumField(fn *ssa.Function, args []value) value {
// Signature: func (reflect.Value) int
return len(rV2V(args[0]).(structure))

View File

@ -543,3 +543,18 @@ func init() {
}()
_ = i == j // interface comparison recurses on types
}
// Composite literals
func init() {
type M map[int]int
m1 := []*M{{1: 1}, &M{2: 2}}
want := "map[1:1] map[2:2]"
if got := fmt.Sprint(*m1[0], *m1[1]); got != want {
panic(got)
}
m2 := []M{{1: 1}, M{2: 2}}
if got := fmt.Sprint(m2[0], m2[1]); got != want {
panic(got)
}
}

View File

@ -359,7 +359,7 @@ func toWriter(w io.Writer, v value) {
case map[value]value:
io.WriteString(w, "map[")
sep := " "
sep := ""
for k, e := range v {
io.WriteString(w, sep)
sep = " "