Ejemplo n.º 1
0
// prepareCall determines the function value and argument values for a
// function call in a Call, Go or Defer instruction, peforming
// interface method lookup if needed.
//
func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) {
	if call.Func != nil {
		// Function call.
		fn = fr.get(call.Func)
	} else {
		// Interface method invocation.
		recv := fr.get(call.Recv).(iface)
		if recv.t == nil {
			panic("method invoked on nil interface")
		}
		meth := underlyingType(call.Recv.Type()).(*types.Interface).Methods[call.Method]
		id := ssa.IdFromQualifiedName(meth.QualifiedName)
		m := findMethodSet(fr.i, recv.t)[id]
		if m == nil {
			// Unreachable in well-typed programs.
			panic(fmt.Sprintf("method set for dynamic type %v does not contain %s", recv.t, id))
		}
		_, aptr := recv.v.(*value)                        // actual pointerness
		_, fptr := m.Signature.Recv.Type.(*types.Pointer) // formal pointerness
		switch {
		case aptr == fptr:
			args = append(args, copyVal(recv.v))
		case aptr:
			// Calling func(T) with a *T receiver: make a copy.
			args = append(args, copyVal(*recv.v.(*value)))
		case fptr:
			panic("illegal call of *T method with T receiver")
		}
		fn = m
	}
	for _, arg := range call.Args {
		args = append(args, fr.get(arg))
	}
	return
}
Ejemplo n.º 2
0
// checkInterface checks that the method set of x implements the
// interface itype.
// On success it returns "", on failure, an error message.
//
func checkInterface(i *interpreter, itype types.Type, x iface) string {
	mset := findMethodSet(i, x.t)
	for _, m := range underlyingType(itype).(*types.Interface).Methods {
		id := ssa.IdFromQualifiedName(m.QualifiedName)
		if mset[id] == nil {
			return fmt.Sprintf("interface conversion: %v is not %v: missing method %v", x.t, itype, id)
		}
	}
	return "" // ok
}