doodl.scm 8.5 KB

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