Beispiel #1
0
func (caller *Function) invoke(common *ssa.CallCommon, infer *TypeInfer, b *Block, l *Loop) *Function {
	iface, ok := common.Value.Type().Underlying().(*types.Interface)
	if !ok {
		infer.Logger.Fatalf("invoke: %s is not an interface", common.String())
		return nil
	}
	ifaceInst, ok := caller.locals[common.Value] // SSA value initialised
	if !ok {
		infer.Logger.Fatalf("invoke: %s: %s", common.Value.Name(), ErrUnknownValue)
		return nil
	}
	switch inst := ifaceInst.(type) {
	case *Value: // OK
	case *Const:
		if inst.Const.IsNil() {
			return nil
		}
		infer.Logger.Fatalf("invoke: %+v is not nil nor concrete", ifaceInst)
	case *External:
		infer.Logger.Printf(caller.Sprintf("invoke: %+v external", ifaceInst))
		return nil
	default:
		infer.Logger.Printf(caller.Sprintf("invoke: %+v unknown", ifaceInst))
		return nil
	}
	meth, _ := types.MissingMethod(ifaceInst.(*Value).Type(), iface, true) // static
	if meth != nil {
		meth, _ = types.MissingMethod(ifaceInst.(*Value).Type(), iface, false) // non-static
		if meth != nil {
			infer.Logger.Printf("invoke: missing method %s: %s", meth.String(), ErrIfaceIncomplete)
			return nil
		}
	}
	fn := findMethod(common.Value.Parent().Prog, common.Method, ifaceInst.(*Value).Type(), infer)
	if fn == nil {
		if meth == nil {
			infer.Logger.Printf("invoke: cannot locate concrete method")
		} else {
			infer.Logger.Printf("invoke: cannot locate concrete method: %s", meth.String())
		}
		return nil
	}
	return caller.call(common, fn, common.Value, infer, b, l)
}