package muesli

// CallableValue is is both a Value and a Callable.
type CallableValue interface {
	Callable
	Value
}

// Redispath takes the first argument i args, and if that is a word,
// calls the command named by that word, replacing the target CalableValue
// as the first argument. This allows some OOP style trickery where
// custom_value foo gets called as foo custom_value where custom_value is 
// of CustomType. 
// In this case foo should the be an overloaded command that takes CustomType.  
func Redispatch(target CallableValue, vm *VM, args...Value) []Value {
	if len(args) < 1 {
		return EmptyValueArray()		
	}
	var word WordValue 
	_, err := ParseOptArgs(args, 1, &word)
	if err != nil {
		return Fail(err)
	}	
	args[0] = target
	vm.Trace("Redispatching with args %v\n", args)
	return vm.CallNamed(string(word), args...)
} 


// RedispatchCallable can be embedded into a type to allow it to 
// become redispatchable, that is, it can support OOP style
// calling of pseudo methods by rearranging the command.  
type RedispatchCallable struct {
    target CallableValue
    BasicCallable    
}

func (rc * RedispatchCallable) Call(vm *VM, args...Value) []Value {
	if (rc.target == nil) {
		return Fail(NewErrorValuef("Cannot redispatch call due to nil target."))
	}
	return Redispatch(rc.target, vm, args...)
}

var _ Callable = &RedispatchCallable{}

func NewRedispatchCallable(name string, value CallableValue) RedispatchCallable {
    return RedispatchCallable{target: value, BasicCallable: NewBasicCallable(name)}
}

var _ Callable = &ListValue{}