コード例 #1
0
ファイル: ops.go プロジェクト: jeremiah/go-xslate
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)
		}
	}
}
コード例 #2
0
ファイル: ops.go プロジェクト: shawnps/go-xslate
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()
}