alsos.body.scm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. ;;;;; Foundational procedure definitions:
  2. ;;;;; has-ancestors? get-ancestors get-handler has-handler? resend send
  3. (define (has-ancestors? obj)
  4. (let ((result (assq 'ancestors obj)))
  5. (and result
  6. (cdr result)
  7. (procedure? (cdr result))
  8. (let ((ancestors ((cdr result) obj)))
  9. (and (list? ancestors)
  10. (not (null? ancestors)))))))
  11. (define (get-ancestors obj)
  12. (if (has-ancestors? obj)
  13. ((cdr (assq 'ancestors obj)) obj)
  14. '()))
  15. (define (get-handler del msg)
  16. (and (list? del)
  17. (let ((handler (assq msg del)))
  18. (if handler
  19. handler
  20. (and (has-ancestors? del)
  21. (let loop ((ancestors (get-ancestors del)))
  22. (if (null? ancestors)
  23. #f
  24. (if (get-handler (car ancestors) msg)
  25. (get-handler (car ancestors) msg)
  26. (loop (cdr ancestors))))))))))
  27. (define (has-handler? obj msg)
  28. (if (get-handler obj msg) #t #f))
  29. (define (resend obj del msg . args)
  30. (let ((handler (get-handler del msg)))
  31. (if handler
  32. (if (or (procedure? (cdr handler))
  33. (not (null? args)))
  34. (apply (cdr handler) obj args)
  35. (cdr handler))
  36. ;; allow overriding behavior with message-not-understood
  37. (let ((not-understood-handler (get-handler del 'message-not-understood)))
  38. (if (and not-understood-handler (procedure? (cdr not-understood-handler)))
  39. ((cdr not-understood-handler) obj msg args)
  40. (error "send" "Message not understood" msg))))))
  41. (define (send obj msg . args)
  42. (apply resend obj obj msg args))
  43. ;;;;; Syntax for defining operations:
  44. ;;;;; define-predicate define-operation
  45. (define-syntax define-predicate
  46. (syntax-rules ()
  47. ((_ name)
  48. (define (name obj)
  49. (and (list? obj)
  50. (has-handler? obj 'name)
  51. (send obj 'name))))))
  52. (define-syntax define-operation
  53. (syntax-rules ()
  54. ((_ (name obj args ...))
  55. (define (name obj args ...)
  56. (send obj 'name args ...)))
  57. ((_ (name obj args ...) default-behavior ...)
  58. (define (name obj args ...)
  59. (if (has-handler? obj 'name)
  60. (send obj 'name args ...)
  61. (let ()
  62. default-behavior ...))))
  63. ((_ (name obj . args))
  64. (define (name obj . args)
  65. (apply send obj 'name args)))
  66. ((_ (name obj . args) default-behavior ...)
  67. (define (name obj . args)
  68. (if (has-handler? obj 'name)
  69. (apply send obj 'name args)
  70. (let ()
  71. default-behavior ...))))))
  72. ;;;;; Syntax for creating objects and resending:
  73. ;;;;; object object-with-ancestors operate-as
  74. (define-syntax object
  75. (syntax-rules ()
  76. ((_) '())
  77. ((_ ((msg self args ...) behavior ...) rest ...)
  78. (cons
  79. (cons 'msg
  80. (lambda (self args ...)
  81. behavior ...))
  82. (object rest ...)))
  83. ((_ ((msg self . args) behavior ...) rest ...)
  84. (cons
  85. (cons 'msg
  86. (lambda (self . args)
  87. behavior ...))
  88. (object rest ...)))))
  89. (define-syntax object-with-ancestors
  90. (syntax-rules ()
  91. ((_ ((ancestor1 init1) ...) rest ...)
  92. (let ((ancestor1 init1) ...)
  93. (cons
  94. (cons 'ancestors
  95. (lambda (self)
  96. (list ancestor1 ...)))
  97. (object rest ...))))))
  98. (define-syntax operate-as
  99. (syntax-rules ()
  100. ((_ del msg obj args ...)
  101. (resend obj del msg args ...))))
  102. ;;;;; Other helpful operations
  103. ;;;;; protocol simplify-object
  104. (define (remove-dupes l)
  105. ;; remove duplicate keys from a list
  106. ;; not exported, helper for protocol
  107. (let loop ((result '())
  108. (next l))
  109. (if (null? next)
  110. (reverse result)
  111. (loop (if (memq (car next) result)
  112. result
  113. (cons (car next) result))
  114. (cdr next)))))
  115. (define (expand-ancestors obj)
  116. ;; append an object with its ancestors
  117. ;; not exported, helper for protocol
  118. (append
  119. obj
  120. (apply append (map expand-ancestors (get-ancestors obj)))))
  121. (define protocol
  122. (case-lambda
  123. ((obj)
  124. (remove-dupes (map car (expand-ancestors obj))))
  125. ((obj msg)
  126. (and (has-handler? obj msg)
  127. (cdr (get-handler obj msg))))))
  128. (define (simplify-object obj keys)
  129. ;; sends each key to the object, returning an alist
  130. ;; with the resulting values
  131. (map (lambda (key)
  132. (cons key (send obj key)))
  133. keys))