doodl.scm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Dilapidated Object-Oriented Dynamic Language
  3. ; Dynamic Object-Oriented Dynamic Language
  4. ; Drug-crazed Object-Oriented Dynamic Language
  5. ; Written for clarity, not for speed.
  6. ; Tests are in test-doodl.scm.
  7. (define <object> <value>)
  8. (define <number> <number>)
  9. (define <complex> <complex>)
  10. (define <real> <real>)
  11. (define <rational> <rational>)
  12. (define <integer> <integer>)
  13. (define <pair> <pair>)
  14. (define <symbol> <symbol>)
  15. (define <char> <char>)
  16. (define <null> <null>)
  17. (define <vector> <vector>)
  18. (define <string> <string>)
  19. (define <eof-object> <eof-object>)
  20. (define <function> <procedure>)
  21. (define <input-port> <input-port>)
  22. (define <output-port> <output-port>)
  23. ; --------------------
  24. ; Generic functions
  25. (define method-table? (type-predicate :method-table))
  26. (define-syntax define-generic-function
  27. (syntax-rules (setter)
  28. ((define-generic-function (setter ?name) ?parameter-list) ;for define-slot
  29. (define-setter ?name
  30. (make-generic-function
  31. '(the-setter ?name)
  32. (method-info ?name ("next" next-method . ?parameter-list)
  33. (next-method)))))
  34. ((define-generic-function ?name ?parameter-list)
  35. (define ?name
  36. (make-generic-function
  37. '?name
  38. (method-info ?name ("next" next-method . ?parameter-list)
  39. (next-method)))))))
  40. (define (make-generic-function id prototype)
  41. (let ((mtable (make-method-table id prototype)))
  42. (annotate-procedure (make-generic mtable) mtable)))
  43. (define (generic-function? f)
  44. (and (procedure? f)
  45. (method-table? (procedure-annotation f))))
  46. (define-simple-type <generic-function> (<function>) generic-function?)
  47. (really-define-method &add-method! ((g <generic-function>) foo)
  48. (add-method! (procedure-annotation g) foo))
  49. (really-define-method &disclose ((g <generic-function>))
  50. `(generic-function ,(method-table-id (procedure-annotation g))))
  51. (define method-table-id (record-accessor :method-table 'id))
  52. ; --------------------
  53. ; Method info (applicability / action pairs)
  54. ; D***n-style METHOD syntax
  55. (define-syntax method
  56. (syntax-rules ()
  57. ((method ?specs ?body ...)
  58. (make-method (method-info anonymous ?specs ?body ...)))))
  59. (define method-table-methods (record-accessor :method-table 'methods))
  60. (define (make-method info)
  61. (letrec ((perform (methods->perform
  62. (list info
  63. (method-info method args
  64. (apply assertion-violation 'make-method
  65. "invalid arguments" m args)))
  66. ;; This oughta be a prototype
  67. #f))
  68. (m (annotate-procedure (lambda args (perform args))
  69. info)))
  70. m))
  71. (define method-info? (record-predicate :method-info))
  72. (define (method? f)
  73. (and (procedure? f)
  74. (method-info? (procedure-annotation f))))
  75. (define-simple-type <method> (<function>) method?)
  76. (really-define-method &disclose ((m <method>))
  77. `(method ,(procedure-annotation m)))
  78. (define-syntax define-method
  79. (syntax-rules (setter)
  80. ((define-method (setter ?id) ?formals ?body ...)
  81. (really-define-setter-method ?id ?formals 'bar ?body ...))
  82. ((define-method ?id ?formals ?body ...)
  83. (really-define-method ?id ?formals 'foo ?body ...))))
  84. (define-syntax really-define-setter-method
  85. (lambda (e r c)
  86. `(,(r 'really-define-method)
  87. ,(string->symbol (string-append (symbol->string (cadr e))
  88. "-"
  89. (symbol->string 'setter)))
  90. ,@(cddr e))))
  91. ; --------------------
  92. ; (SETTER foo)
  93. (define-syntax the-setter
  94. (lambda (e r c)
  95. (string->symbol (string-append (symbol->string (cadr e))
  96. "-"
  97. (symbol->string 'setter)))))
  98. (define-syntax define-setter
  99. (lambda (e r c)
  100. `(,(r 'define)
  101. ,(string->symbol (string-append (symbol->string (cadr e))
  102. "-"
  103. (symbol->string 'setter)))
  104. ,(caddr e))))
  105. (define-syntax set
  106. (syntax-rules ()
  107. ((set (?fun ?arg ...) ?val)
  108. ((the-setter ?fun) ?arg ... ?val))
  109. ((set ?var ?val)
  110. (set! ?var ?val))))
  111. (define car-setter set-car!)
  112. (define cdr-setter set-cdr!)
  113. (define vector-ref-setter vector-set!)
  114. ; --------------------
  115. ; DEFINE-CLASS
  116. (define-syntax define-class
  117. (syntax-rules ()
  118. ((define-class ?class-name (?super ...) ?slot ...)
  119. (begin (define-slot ?slot)
  120. ...
  121. (define ?class-name
  122. (make-class (list ?super ...)
  123. (list ?slot ...)
  124. '?class-name))))))
  125. (define-syntax define-slot
  126. (syntax-rules ()
  127. ((define-slot ?slot)
  128. (begin (define-generic-function ?slot (x))
  129. (define-generic-function (setter ?slot) (x new-val))
  130. (define-method ?slot ((x <instance>))
  131. (instance-slot-ref x ?slot))
  132. (define-setter-method ?slot ((x <instance>) new-val)
  133. (instance-slot-set! x ?slot new-val))))))
  134. (define-syntax define-setter-method
  135. (lambda (e r c)
  136. `(,(r 'define-method)
  137. ,(string->symbol (string-append (symbol->string (cadr e))
  138. "-"
  139. (symbol->string 'setter)))
  140. ,@(cddr e))))
  141. ; Instances
  142. (define-record-type instance :instance
  143. (make-instance classes slots)
  144. instance?
  145. (classes instance-classes)
  146. (slots instance-slot-values))
  147. (define (instance-slot-ref instance slot)
  148. (cond ((assq slot (instance-slot-values instance)) => cdr)
  149. (else (assertion-violation 'instance-slot-ref "no such slot"
  150. instance slot))))
  151. (define (instance-slot-set! instance slot new-value)
  152. (cond ((assq slot (instance-slot-values instance))
  153. => (lambda (z) (set-cdr! z new-value)))
  154. (else (assertion-violation 'instance-slot-set! "no such slot"
  155. instance slot new-value))))
  156. ; Classes
  157. (define-record-type class :class
  158. (really-make-class classes predicate priority slots id)
  159. class?
  160. (classes class-classes)
  161. (predicate class-predicate)
  162. (priority class-priority)
  163. (slots class-slots)
  164. (id class-id))
  165. (define-record-discloser :class
  166. (lambda (c) `(class ,(class-id c))))
  167. (really-define-method &type-predicate ((c :class)) (class-predicate c))
  168. (really-define-method &type-priority ((c :class)) (class-priority c))
  169. (define (make-class supers slots id)
  170. (letrec ((class
  171. (really-make-class
  172. (reduce unionq '() (map get-classes supers))
  173. (lambda (x) ;Predicate
  174. (and (instance? x)
  175. (memq class (instance-classes x))))
  176. (if (null? supers) ;Priority
  177. (type-priority :instance)
  178. (+ (apply max (map type-priority supers))
  179. *increment*))
  180. (unionq slots
  181. (reduce unionq '() (map get-slots supers)))
  182. id)))
  183. class))
  184. (define *increment* 10)
  185. (define (get-classes type)
  186. (if (class? type)
  187. (cons type
  188. (class-classes type))
  189. '()))
  190. (define (get-slots type)
  191. (if (class? type)
  192. (class-slots type)
  193. '()))
  194. (define-generic-function make (class . key/value-pairs))
  195. (define-method make ((c :class) . key/value-pairs)
  196. (let ((i (make-instance (cons c (class-classes c))
  197. (map (lambda (slot)
  198. (cons slot '*uninitialized*))
  199. (class-slots c)))))
  200. (apply initialize i key/value-pairs)
  201. i))
  202. (define-generic-function initialize (i . key/value-pairs))
  203. (define-method initialize ((i :instance)) (unspecific))
  204. (define (unionq l1 l2)
  205. (cond ((null? l1) l2)
  206. ((null? l2) l1)
  207. ((memq (car l1) l2) (unionq (cdr l1) l2))
  208. (else (cons (car l1) (unionq (cdr l1) l2)))))
  209. ; --------------------
  210. ; Random
  211. (define id? eq?)
  212. (define-syntax bind
  213. (lambda (e r c)
  214. (if (and (pair? (cdr e))
  215. (list? (cadr e)))
  216. (let ((%call-with-values (r 'call-with-values))
  217. (%lambda (r 'lambda))
  218. (%method (r 'method))
  219. (%begin (r 'begin)))
  220. (let recur ((specs (cadr e)))
  221. (if (null? specs)
  222. `(,%begin ,@(cddr e))
  223. (let ((rspec (reverse (car specs))))
  224. `(,%call-with-values
  225. (,%lambda () ,(car rspec))
  226. (,%method ,(reverse (cdr rspec))
  227. ,(recur (cdr specs))))))))
  228. e)))
  229. (define-simple-type <list> (<object>) list?)
  230. ; --------------------
  231. ; More?
  232. ; (instance? obj class)
  233. ; (as class object) => instance
  234. ; <type>
  235. ; (union type1 type2)
  236. ; (union* type ...)
  237. ; (subtype? type1 type2 )
  238. ; per design note 05
  239. ; (define-method foo (x y #values (foo <integer>)) ...)
  240. ; per design note 21
  241. ; (define-method f ((x (limited <integer> min: -1000 max: 1000)) ...)
  242. ; ...)
  243. ; design note 06
  244. ; <collection>, etc.
  245. ; <exact> and <inexact> ?
  246. ;(define <sequence>
  247. ; (make-generalization (list <list> <vector> <string>) '<sequence>))
  248. ;(define <port>
  249. ; (make-generalization (list <input-port> <output-port>) '<port>))
  250. ; Need reader syntax:
  251. ; #next #rest #key etc.
  252. ; - implement with (define-sharp-macro #\n ...) ?
  253. ; keywords - foo:
  254. ; - implement by customizing parse-token