doodl.scm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. ; Copyright (c) 1993-2007 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 call-error "invalid arguments" m args)))
  65. ;; This oughta be a prototype
  66. #f))
  67. (m (annotate-procedure (lambda args (perform args))
  68. info)))
  69. m))
  70. (define method-info? (record-predicate :method-info))
  71. (define (method? f)
  72. (and (procedure? f)
  73. (method-info? (procedure-annotation f))))
  74. (define-simple-type <method> (<function>) method?)
  75. (really-define-method &disclose ((m <method>))
  76. `(method ,(procedure-annotation m)))
  77. (define-syntax define-method
  78. (syntax-rules (setter)
  79. ((define-method (setter ?id) ?formals ?body ...)
  80. (really-define-setter-method ?id ?formals 'bar ?body ...))
  81. ((define-method ?id ?formals ?body ...)
  82. (really-define-method ?id ?formals 'foo ?body ...))))
  83. (define-syntax really-define-setter-method
  84. (lambda (e r c)
  85. `(,(r 'really-define-method)
  86. ,(string->symbol (string-append (symbol->string (cadr e))
  87. "-"
  88. (symbol->string 'setter)))
  89. ,@(cddr e))))
  90. ; --------------------
  91. ; (SETTER foo)
  92. (define-syntax the-setter
  93. (lambda (e r c)
  94. (string->symbol (string-append (symbol->string (cadr e))
  95. "-"
  96. (symbol->string 'setter)))))
  97. (define-syntax define-setter
  98. (lambda (e r c)
  99. `(,(r 'define)
  100. ,(string->symbol (string-append (symbol->string (cadr e))
  101. "-"
  102. (symbol->string 'setter)))
  103. ,(caddr e))))
  104. (define-syntax set
  105. (syntax-rules ()
  106. ((set (?fun ?arg ...) ?val)
  107. ((the-setter ?fun) ?arg ... ?val))
  108. ((set ?var ?val)
  109. (set! ?var ?val))))
  110. (define car-setter set-car!)
  111. (define cdr-setter set-cdr!)
  112. (define vector-ref-setter vector-set!)
  113. ; --------------------
  114. ; DEFINE-CLASS
  115. (define-syntax define-class
  116. (syntax-rules ()
  117. ((define-class ?class-name (?super ...) ?slot ...)
  118. (begin (define-slot ?slot)
  119. ...
  120. (define ?class-name
  121. (make-class (list ?super ...)
  122. (list ?slot ...)
  123. '?class-name))))))
  124. (define-syntax define-slot
  125. (syntax-rules ()
  126. ((define-slot ?slot)
  127. (begin (define-generic-function ?slot (x))
  128. (define-generic-function (setter ?slot) (x new-val))
  129. (define-method ?slot ((x <instance>))
  130. (instance-slot-ref x ?slot))
  131. (define-setter-method ?slot ((x <instance>) new-val)
  132. (instance-slot-set! x ?slot new-val))))))
  133. (define-syntax define-setter-method
  134. (lambda (e r c)
  135. `(,(r 'define-method)
  136. ,(string->symbol (string-append (symbol->string (cadr e))
  137. "-"
  138. (symbol->string 'setter)))
  139. ,@(cddr e))))
  140. ; Instances
  141. (define-record-type instance <instance>
  142. (make-instance classes slots)
  143. instance?
  144. (classes instance-classes)
  145. (slots instance-slot-values))
  146. (define (instance-slot-ref instance slot)
  147. (cond ((assq slot (instance-slot-values instance)) => cdr)
  148. (else (call-error "no such slot"
  149. instance-slot-ref instance slot))))
  150. (define (instance-slot-set! instance slot new-value)
  151. (cond ((assq slot (instance-slot-values instance))
  152. => (lambda (z) (set-cdr! z new-value)))
  153. (else (call-error "no such slot"
  154. instance-slot-set! instance slot new-value))))
  155. ; Classes
  156. (define-record-type class <class>
  157. (really-make-class classes predicate priority slots id)
  158. class?
  159. (classes class-classes)
  160. (predicate class-predicate)
  161. (priority class-priority)
  162. (slots class-slots)
  163. (id class-id))
  164. (define-record-discloser <class>
  165. (lambda (c) `(class ,(class-id c))))
  166. (really-define-method &type-predicate ((c <class>)) (class-predicate c))
  167. (really-define-method &type-priority ((c <class>)) (class-priority c))
  168. (define (make-class supers slots id)
  169. (letrec ((class
  170. (really-make-class
  171. (reduce unionq '() (map get-classes supers))
  172. (lambda (x) ;Predicate
  173. (and (instance? x)
  174. (memq class (instance-classes x))))
  175. (if (null? supers) ;Priority
  176. (type-priority <instance>)
  177. (+ (apply max (map type-priority supers))
  178. *increment*))
  179. (unionq slots
  180. (reduce unionq '() (map get-slots supers)))
  181. id)))
  182. class))
  183. (define *increment* 10)
  184. (define (get-classes type)
  185. (if (class? type)
  186. (cons type
  187. (class-classes type))
  188. '()))
  189. (define (get-slots type)
  190. (if (class? type)
  191. (class-slots type)
  192. '()))
  193. (define-generic-function make (class . key/value-pairs))
  194. (define-method make ((c <class>) . key/value-pairs)
  195. (let ((i (make-instance (cons c (class-classes c))
  196. (map (lambda (slot)
  197. (cons slot '*uninitialized*))
  198. (class-slots c)))))
  199. (apply initialize i key/value-pairs)
  200. i))
  201. (define-generic-function initialize (i . key/value-pairs))
  202. (define-method initialize ((i <instance>)) (unspecific))
  203. (define (unionq l1 l2)
  204. (cond ((null? l1) l2)
  205. ((null? l2) l1)
  206. ((memq (car l1) l2) (unionq (cdr l1) l2))
  207. (else (cons (car l1) (unionq (cdr l1) l2)))))
  208. ; --------------------
  209. ; Random
  210. (define id? eq?)
  211. (define-syntax bind
  212. (lambda (e r c)
  213. (if (and (pair? (cdr e))
  214. (list? (cadr e)))
  215. (let ((%call-with-values (r 'call-with-values))
  216. (%lambda (r 'lambda))
  217. (%method (r 'method))
  218. (%begin (r 'begin)))
  219. (let recur ((specs (cadr e)))
  220. (if (null? specs)
  221. `(,%begin ,@(cddr e))
  222. (let ((rspec (reverse (car specs))))
  223. `(,%call-with-values
  224. (,%lambda () ,(car rspec))
  225. (,%method ,(reverse (cdr rspec))
  226. ,(recur (cdr specs))))))))
  227. e)))
  228. (define-simple-type <list> (<object>) list?)
  229. ; --------------------
  230. ; More?
  231. ; (instance? obj class)
  232. ; (as class object) => instance
  233. ; <type>
  234. ; (union type1 type2)
  235. ; (union* type ...)
  236. ; (subtype? type1 type2 )
  237. ; per design note 05
  238. ; (define-method foo (x y #values (foo <integer>)) ...)
  239. ; per design note 21
  240. ; (define-method f ((x (limited <integer> min: -1000 max: 1000)) ...)
  241. ; ...)
  242. ; design note 06
  243. ; <collection>, etc.
  244. ; <exact> and <inexact> ?
  245. ;(define <sequence>
  246. ; (make-generalization (list <list> <vector> <string>) '<sequence>))
  247. ;(define <port>
  248. ; (make-generalization (list <input-port> <output-port>) '<port>))
  249. ; Need reader syntax:
  250. ; #next #rest #key etc.
  251. ; - implement with (define-sharp-macro #\n ...) ?
  252. ; keywords - foo:
  253. ; - implement by customizing parse-token