redispatch.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package muesli
  2. // CallableValue is is both a Value and a Callable.
  3. type CallableValue interface {
  4. Callable
  5. Value
  6. }
  7. // Redispath takes the first argument i args, and if that is a word,
  8. // calls the command named by that word, replacing the target CalableValue
  9. // as the first argument. This allows some OOP style trickery where
  10. // custom_value foo gets called as foo custom_value where custom_value is
  11. // of CustomType.
  12. // In this case foo should the be an overloaded command that takes CustomType.
  13. func Redispatch(target CallableValue, vm *VM, args...Value) []Value {
  14. if len(args) < 1 {
  15. return EmptyValueArray()
  16. }
  17. var word WordValue
  18. _, err := ParseOptArgs(args, 1, &word)
  19. if err != nil {
  20. return Fail(err)
  21. }
  22. args[0] = target
  23. vm.Trace("Redispatching with args %v\n", args)
  24. return vm.CallNamed(string(word), args...)
  25. }
  26. // RedispatchCallable can be embedded into a type to allow it to
  27. // become redispatchable, that is, it can support OOP style
  28. // calling of pseudo methods by rearranging the command.
  29. type RedispatchCallable struct {
  30. target CallableValue
  31. BasicCallable
  32. }
  33. func (rc * RedispatchCallable) Call(vm *VM, args...Value) []Value {
  34. if (rc.target == nil) {
  35. return Fail(NewErrorValuef("Cannot redispatch call due to nil target."))
  36. }
  37. return Redispatch(rc.target, vm, args...)
  38. }
  39. var _ Callable = &RedispatchCallable{}
  40. func NewRedispatchCallable(name string, value CallableValue) RedispatchCallable {
  41. return RedispatchCallable{target: value, BasicCallable: NewBasicCallable(name)}
  42. }
  43. var _ Callable = &ListValue{}