func txMethodCall(st *State) { defer st.Advance() // We advance, regardless of errors name := interfaceToString(st.CurrentOp().Arg()) // Uppercase first character of field name r, size := utf8.DecodeRuneInString(name) name = string(unicode.ToUpper(r)) + name[size:] mark := st.CurrentMark() tip := st.stack.Size() var invocant reflect.Value args := make([]reflect.Value, tip-mark) for i := mark; i < tip; i++ { v := st.stack.Pop() args[tip-i-1] = reflect.ValueOf(v) if i == mark { invocant = args[tip-i-1] } } // For maps, arrays, slices, we call virtual methods, if they are available switch invocant.Kind() { case reflect.Map: fun, ok := hash.Depot().Get(name) if ok { invokeFuncSingleReturn(st, fun, args) } case reflect.Array, reflect.Slice: // Array/Slices cannot be passed as []interface {} or any other // generic way, so we need to re-allocate the argument to a more // generic []interface {} container before dispatching it list := make([]interface{}, invocant.Len()) for i := 0; i < invocant.Len(); i++ { list[i] = invocant.Index(i).Interface() } args[0] = reflect.ValueOf(list) fun, ok := array.Depot().Get(name) if ok { invokeFuncSingleReturn(st, fun, args) } default: method, ok := invocant.Type().MethodByName(name) if !ok { st.sa = nil } else { invokeFuncSingleReturn(st, method.Func, args) } } }
func txMethodCall(st *State) { name := interfaceToString(st.CurrentOp().Arg()) // Uppercase first character of field name r, size := utf8.DecodeRuneInString(name) name = string(unicode.ToUpper(r)) + name[size:] // Everything in our lvars up to the current tip is our argument list mark := st.CurrentMark() tip := st.stack.Cur() v, _ := st.stack.Get(mark) invocant := reflect.ValueOf(v) var args = make([]reflect.Value, tip-mark+1) for i := mark; tip >= i; i++ { v, _ := st.stack.Get(i) args[i-mark] = reflect.ValueOf(v) } // For maps, arrays, slices, we call virtual methods, if they are available switch invocant.Kind() { case reflect.Map: fun, ok := hash.Depot().Get(name) if ok { invokeFuncSingleReturn(st, fun, args) } case reflect.Array, reflect.Slice: // Array/Slices cannot be passed as []interface {} or any other // generic way, so we need to re-allocate the argument to a more // generic []interface {} container before dispatching it list := make([]interface{}, invocant.Len()) for i := 0; i < invocant.Len(); i++ { list[i] = invocant.Index(i).Interface() } args[0] = reflect.ValueOf(list) fun, ok := array.Depot().Get(name) if ok { invokeFuncSingleReturn(st, fun, args) } default: method, ok := invocant.Type().MethodByName(name) if !ok { st.sa = nil } else { invokeFuncSingleReturn(st, method.Func, args) } } st.Advance() }