PageRenderTime 59ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/runtime-methods.scm

http://github.com/pablomarx/Thomas
Scheme | 840 lines | 692 code | 95 blank | 53 comment | 2 complexity | b4f117b184507ee51e2aa13c16b5f34c MD5 | raw file
  1. ;* Copyright 1992 Digital Equipment Corporation
  2. ;* All Rights Reserved
  3. ;*
  4. ;* Permission to use, copy, and modify this software and its documentation is
  5. ;* hereby granted only under the following terms and conditions. Both the
  6. ;* above copyright notice and this permission notice must appear in all copies
  7. ;* of the software, derivative works or modified versions, and any portions
  8. ;* thereof, and both notices must appear in supporting documentation.
  9. ;*
  10. ;* Users of this software agree to the terms and conditions set forth herein,
  11. ;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
  12. ;* right and license under any changes, enhancements or extensions made to the
  13. ;* core functions of the software, including but not limited to those affording
  14. ;* compatibility with other hardware or software environments, but excluding
  15. ;* applications which incorporate this software. Users further agree to use
  16. ;* their best efforts to return to Digital any such changes, enhancements or
  17. ;* extensions that they make and inform Digital of noteworthy uses of this
  18. ;* software. Correspondence should be provided to Digital at:
  19. ;*
  20. ;* Director, Cambridge Research Lab
  21. ;* Digital Equipment Corp
  22. ;* One Kendall Square, Bldg 700
  23. ;* Cambridge MA 02139
  24. ;*
  25. ;* This software may be distributed (but not offered for sale or transferred
  26. ;* for compensation) to third parties, provided such third parties agree to
  27. ;* abide by the terms and conditions of this notice.
  28. ;*
  29. ;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  30. ;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  31. ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  32. ;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  33. ;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  34. ;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  35. ;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  36. ;* SOFTWARE.
  37. ; $Id: runtime-methods.scm,v 1.25 1992/09/19 06:54:56 birkholz Exp $
  38. ;;;; Methods used in the Dylan environment
  39. ;;; Methods (not generically dispatched)
  40. ;; dylan::function->method has been moved to support.scm -- it takes in
  41. ;; a scheme function and converts it to a Dylan-callable procedure by
  42. ;; ignoring the multiple-values and next-method arguments that come from Dylan.
  43. (define dylan:+
  44. (dylan::function->method
  45. only-rest-args
  46. (lambda rest-args
  47. (if (null? rest-args)
  48. 0
  49. (let loop ((rest (cdr rest-args))
  50. (sum (car rest-args)))
  51. (if (null? rest)
  52. sum
  53. (loop (cdr rest)
  54. (dylan-call dylan:binary+ sum (car rest)))))))))
  55. (define dylan:*
  56. (dylan::function->method
  57. only-rest-args
  58. (lambda rest-args
  59. (if (null? rest-args)
  60. 1
  61. (let loop ((rest (cdr rest-args))
  62. (sum (car rest-args)))
  63. (if (null? rest)
  64. sum
  65. (loop (cdr rest)
  66. (dylan-call dylan:binary* sum (car rest)))))))))
  67. (define dylan:-
  68. (dylan::function->method
  69. at-least-one-number
  70. (lambda (num . rest-num)
  71. (if (null? rest-num)
  72. (- num)
  73. (let loop ((rest rest-num)
  74. (sum num))
  75. (if (null? rest)
  76. sum
  77. (loop (cdr rest)
  78. (dylan-call dylan:binary- sum (car rest)))))))))
  79. (define dylan:/
  80. (dylan::function->method
  81. at-least-one-number
  82. (lambda (num . rest-num)
  83. (if (null? rest-num)
  84. (/ num)
  85. (let loop ((rest rest-num)
  86. (sum num))
  87. (if (null? rest)
  88. sum
  89. (loop (cdr rest)
  90. (dylan-call dylan:binary/ sum (car rest)))))))))
  91. (define dylan:identity (dylan::function->method one-object (lambda (x) x)))
  92. (define dylan:=
  93. (dylan::function->method
  94. at-least-two-objects
  95. (lambda (obj1 obj2 . rest-objs)
  96. (if (dylan-call dylan:binary= obj1 obj2)
  97. (let loop ((rest-objs rest-objs))
  98. (if (null? rest-objs)
  99. #T
  100. (if (dylan-call dylan:binary= obj1 (car rest-objs))
  101. (loop (cdr rest-objs))
  102. #F)))
  103. #F))))
  104. (define dylan:/=
  105. (dylan::function->method
  106. two-objects
  107. (lambda (obj1 obj2) (not (dylan-call dylan:binary= obj1 obj2)))))
  108. (define dylan:<
  109. (dylan::function->method
  110. at-least-two-objects
  111. (lambda (obj1 obj2 . rest-objs)
  112. (if (dylan-call dylan:binary< obj1 obj2)
  113. (let loop ((rest-objs rest-objs)
  114. (prev-obj obj2))
  115. (if (null? rest-objs)
  116. #T
  117. (if (dylan-call dylan:binary< prev-obj (car rest-objs))
  118. (loop (cdr rest-objs) (car rest-objs))
  119. #F)))
  120. #F))))
  121. (define dylan:>=
  122. (dylan::function->method
  123. at-least-two-objects
  124. (lambda (obj1 obj2 . rest-objs)
  125. (if (not (dylan-call dylan:binary< obj1 obj2))
  126. (let loop ((rest-objs rest-objs)
  127. (prev-obj obj2))
  128. (if (null? rest-objs)
  129. #T
  130. (if (not (dylan-call dylan:binary< prev-obj (car rest-objs)))
  131. (loop (cdr rest-objs) (car rest-objs))
  132. #F)))
  133. #F))))
  134. (define dylan:>
  135. (dylan::function->method
  136. at-least-two-objects
  137. (lambda (obj1 obj2 . rest-objs)
  138. (if (not (or (dylan-call dylan:binary< obj1 obj2)
  139. (dylan-call dylan:binary= obj1 obj2)))
  140. (let loop ((rest-objs rest-objs)
  141. (prev-obj obj2))
  142. (if (null? rest-objs)
  143. #T
  144. (if (not (or (dylan-call dylan:binary< prev-obj (car rest-objs))
  145. (dylan-call dylan:binary=
  146. prev-obj (car rest-objs))))
  147. (loop (cdr rest-objs) (car rest-objs))
  148. #F)))
  149. #F))))
  150. (define dylan:<=
  151. (dylan::function->method
  152. at-least-two-objects
  153. (lambda (obj1 obj2 . rest-objs)
  154. (if (or (dylan-call dylan:binary< obj1 obj2)
  155. (dylan-call dylan:binary= obj1 obj2))
  156. (let loop ((rest-objs rest-objs)
  157. (prev-obj obj2))
  158. (if (null? rest-objs)
  159. #T
  160. (if (or (dylan-call dylan:binary< prev-obj (car rest-objs))
  161. (dylan-call dylan:binary= prev-obj (car rest-objs)))
  162. (loop (cdr rest-objs) (car rest-objs))
  163. #F)))
  164. #F))))
  165. (define dylan:always
  166. (dylan::function->method
  167. one-object
  168. (lambda (obj)
  169. (lambda args
  170. args ; Ignored
  171. obj))))
  172. (define dylan:id?
  173. (dylan::function->method
  174. at-least-two-objects
  175. (lambda (obj1 . others)
  176. (let loop ((rest others))
  177. (or (null? rest)
  178. (and (eq? obj1 (car rest))
  179. (loop (cdr rest))))))))
  180. (define dylan:min
  181. (dylan::function->method
  182. at-least-one-real
  183. (lambda (real1 . others)
  184. (let loop ((rest others)
  185. (min-so-far real1))
  186. (if (null? rest)
  187. min-so-far
  188. (loop (cdr rest)
  189. (if (dylan-call dylan:binary< real1 (car rest))
  190. real1
  191. (car rest))))))))
  192. (define dylan:max
  193. (dylan::function->method
  194. at-least-one-real
  195. (lambda (real1 . others)
  196. (let loop ((rest others)
  197. (max-so-far real1))
  198. (if (null? rest)
  199. max-so-far
  200. (loop (cdr rest)
  201. (if (not (dylan-call dylan:binary< real1 (car rest)))
  202. real1
  203. (car rest))))))))
  204. (define (reduce l fn init-value)
  205. (if (null? l)
  206. init-value
  207. (reduce (cdr l) fn (fn (car l) init-value))))
  208. (define dylan:lcm
  209. (dylan::function->method
  210. only-rest-args
  211. (lambda args
  212. (reduce args (lambda (x) (dylan-call dylan:binary-lcm x)) 1))))
  213. (define dylan:gcd
  214. (dylan::function->method
  215. only-rest-args
  216. (lambda args
  217. (reduce args (lambda (x) (dylan-call dylan:binary-gcd x)) 0))))
  218. ;;; Special functions
  219. (define (dylan:values multiple-values? next-method . values)
  220. next-method ; Ignore
  221. (if (not multiple-values?)
  222. (if (null? values) #F (car values))
  223. (let ((last-loc (- (vector-length multiple-values?) 1)))
  224. (do ((index 0 (+ index 1))
  225. (rest values (cdr rest)))
  226. ((or (null? rest) (= index last-loc))
  227. (vector-set! multiple-values? last-loc rest)
  228. multiple-values?) ; Return vector itself. See BIND
  229. (vector-set! multiple-values? index (car rest))))))
  230. (define dylan:not (make-dylan-callable not 1))
  231. ;;; Generic functions
  232. (define (dylan::generic-fn name param-list scheme-operation)
  233. ;; Scheme-Operation can be #F, meaning "no methods initially available"
  234. (let ((generic-function
  235. (dylan::create-generic-function
  236. name
  237. (param-list.nrequired param-list)
  238. (param-list.keys param-list)
  239. (param-list.rest? param-list))))
  240. (if scheme-operation
  241. (add-method generic-function
  242. (dylan::function->method param-list scheme-operation)))
  243. generic-function))
  244. (define (dylan::make-<object> class . rest)
  245. (define (gather-from-slots slot-fn)
  246. (let loop ((keywords '())
  247. (keys (map slot-fn (vector->list (class.slots class)))))
  248. (if (null? keys)
  249. keywords
  250. (loop (if (car keys) (cons (car keys) keywords) keywords)
  251. (cdr keys)))))
  252. (dylan::keyword-validate #F rest #T)
  253. (let ((instance-data (make-vector
  254. (class.instance-data-size class)))
  255. (slots (class.slots class)))
  256. (let ((required (gather-from-slots slot.required-init-keyword)))
  257. (for-each
  258. (lambda (k)
  259. (dylan::find-keyword
  260. rest k (lambda ()
  261. (dylan-call dylan:error
  262. "make -- missing required keyword" k rest))))
  263. required)
  264. (vector-iterate slots
  265. (lambda (i slot)
  266. i ; unused
  267. (initialize-slot! slot rest instance-data '(INSTANCE))))
  268. (let ((result (make-instance class #F instance-data)))
  269. (add-to-population! (class.instances class) result)
  270. (dylan-apply dylan:initialize result rest)
  271. result))))
  272. (define dylan:make
  273. (dylan::generic-fn 'make
  274. (make-param-list `((CLASS ,<class>)) #F #F #T)
  275. dylan::make-<object>))
  276. (define dylan:initialize
  277. (dylan::generic-fn 'initialize
  278. (make-param-list `((OBJECT ,<object>)) #F #F #T)
  279. (lambda (instance . rest) rest instance)))
  280. (define dylan:slot-initialized?
  281. (dylan::generic-fn 'slot-initialized?
  282. (make-param-list `((INSTANCE ,<object>) (GETTER ,<generic-function>))
  283. #F #F #F)
  284. (lambda (instance getter)
  285. (let* ((class (instance.class instance))
  286. (slots (class.slots class))
  287. (the-slot (same-slot-getter-in-slot-vector->slot getter slots)))
  288. (if (not the-slot)
  289. (dylan-call dylan:error
  290. "slot-initialized? -- no such slot"
  291. instance getter class))
  292. (not
  293. (eq? *the-uninitialized-slot-value*
  294. (case (slot.allocation the-slot)
  295. ((VIRTUAL CONSTANT) 'initialized)
  296. ((CLASS) (let ((data-loc (slot.data-location the-slot)))
  297. (vector-ref (class.class-data (car data-loc))
  298. (cdr data-loc))))
  299. ((EACH-SUBCLASS) (vector-ref (class.class-data class)
  300. (slot.data-location the-slot)))
  301. ((INSTANCE) (vector-ref (instance.data instance)
  302. (slot.data-location the-slot)))
  303. (else (dylan-call dylan:error
  304. "slot-initialized? -- bad allocation"
  305. (slot.allocation the-slot)
  306. instance getter class)))))))))
  307. ;;; Arithmetic
  308. (define dylan:odd? (dylan::generic-fn 'odd? one-integer odd?))
  309. (define dylan:even? (dylan::generic-fn 'even? one-integer even?))
  310. (define dylan:zero? (dylan::generic-fn 'zero? one-number zero?))
  311. (define dylan:positive? (dylan::generic-fn 'positive? one-number positive?))
  312. (define dylan:negative? (dylan::generic-fn 'negative? one-real negative?))
  313. (define dylan:integral? (dylan::generic-fn 'integral? one-number integer?))
  314. (define dylan:abs (dylan::generic-fn 'abs one-number abs))
  315. (define dylan:sin (dylan::generic-fn 'sin one-number sin))
  316. (define dylan:cos (dylan::generic-fn 'cos one-number cos))
  317. (define dylan:tan (dylan::generic-fn 'tan one-number tan))
  318. (define dylan:asin (dylan::generic-fn 'asin one-number asin))
  319. (define dylan:acos (dylan::generic-fn 'acos one-number acos))
  320. (define dylan:atan (dylan::generic-fn 'atan one-number atan))
  321. (define dylan:atan2 (dylan::generic-fn 'atan2 two-numbers atan))
  322. (define dylan:exp (dylan::generic-fn 'exp one-number exp))
  323. (define dylan:log (dylan::generic-fn 'log one-number log))
  324. (define dylan:expt (dylan::generic-fn 'expt one-number expt))
  325. (define dylan:sqrt (dylan::generic-fn 'sqrt one-number sqrt))
  326. (define dylan:modulo
  327. (dylan::generic-fn 'modulo two-reals
  328. (lambda (r1 r2)
  329. (let* ((multiple-values (vector #F #F '()))
  330. (floor (dylan-mv-call dylan:floor/ multiple-values r1 r2)))
  331. floor ; Ignored
  332. (vector-ref multiple-values 0)))))
  333. (define dylan:remainder
  334. (dylan::generic-fn 'remainder
  335. two-reals
  336. (lambda (real1 real2)
  337. (- real1 (* real2 (truncate (/ real1 real2)))))))
  338. (define dylan:unary- (dylan::generic-fn 'unary- one-number -))
  339. (define dylan:unary/ (dylan::generic-fn 'unary/ one-number /))
  340. (define dylan:binary+ (dylan::generic-fn 'binary+ two-numbers +))
  341. (define dylan:binary* (dylan::generic-fn 'binary* two-numbers *))
  342. (define dylan:binary- (dylan::generic-fn 'binary- two-numbers -))
  343. (define dylan:binary/ (dylan::generic-fn 'binary/ two-numbers /))
  344. ;;; Class stuff
  345. (define dylan:all-superclasses
  346. (dylan::generic-fn 'all-superclasses
  347. one-class
  348. (lambda (class)
  349. (map-over-all-superclasses! class (lambda x x)))))
  350. (define dylan:direct-superclasses
  351. (dylan::generic-fn 'direct-superclasses one-class class.superclasses))
  352. (define dylan:direct-subclasses
  353. (dylan::generic-fn 'direct-subclasses one-class
  354. (lambda (class)
  355. (population->list (class.subclasses class)))))
  356. (define dylan:instance?
  357. (dylan::generic-fn 'instance?
  358. (make-param-list `((OBJECT ,<object>) (CLASS ,<class>)) #F #F #F)
  359. (lambda (obj class)
  360. (subclass? (get-type obj) class))))
  361. (define dylan:subclass?
  362. (dylan::generic-fn 'subclass?
  363. (make-param-list `((CLASS-1 ,<class>) (CLASS-2 ,<class>)) #F #F #F)
  364. subclass?))
  365. (define dylan:object-class
  366. (dylan::generic-fn 'object-class one-object get-type))
  367. (define dylan:slot-descriptors
  368. (dylan::generic-fn 'slot-descriptors one-class class.slots))
  369. (define dylan:slot-getter
  370. (dylan::generic-fn 'slot-getter one-slot slot.getter))
  371. (define dylan:slot-setter
  372. (dylan::generic-fn 'slot-setter one-slot slot.setter))
  373. (define dylan:slot-type
  374. (dylan::generic-fn 'slot-type one-slot slot.type))
  375. (define dylan:slot-allocation
  376. (dylan::generic-fn 'slot-allocation one-slot slot.allocation))
  377. (define dylan:binary< (dylan::generic-fn 'binary< two-numbers <))
  378. (define dylan:binary=
  379. ;; Use eq? if object not same class.
  380. (dylan::generic-fn 'binary= two-objects eq?))
  381. (add-method dylan:binary= (dylan::function->method two-numbers =))
  382. (define dylan:as-lowercase
  383. ;; Takes <character>s or <string>s.
  384. (dylan::generic-fn 'as-lowercase one-object #F))
  385. (add-method
  386. dylan:as-lowercase
  387. (dylan::function->method
  388. one-char
  389. (lambda (char) (char-downcase char))))
  390. (define dylan:as-uppercase
  391. ;; Takes <character>s or <string>s.
  392. (dylan::generic-fn 'as-uppercase one-object #F))
  393. (add-method
  394. dylan:as-uppercase
  395. (dylan::function->method
  396. one-char
  397. (lambda (char) (char-upcase char))))
  398. (define dylan:=hash (dylan::generic-fn '=hash one-integer (lambda (x) x)))
  399. (add-method dylan:=hash ; ***** TEMP: for debugging tables
  400. (dylan::function->method
  401. one-real
  402. (lambda (real)
  403. (dylan-call dylan:as <integer> (dylan-call dylan:floor real)))))
  404. (define dylan:floor (dylan::generic-fn 'floor one-real #F))
  405. (add-method
  406. dylan:floor
  407. (dylan::dylan-callable->method
  408. one-real
  409. (lambda (multiple-values next-method num)
  410. next-method
  411. (dylan-mv-call dylan:values multiple-values
  412. (floor num) (- num (floor num))))))
  413. (define dylan:ceiling (dylan::generic-fn 'ceiling one-real #F))
  414. (add-method
  415. dylan:ceiling
  416. (dylan::dylan-callable->method
  417. one-real
  418. (lambda (multiple-values next-method num)
  419. next-method
  420. (dylan-mv-call dylan:values multiple-values
  421. (ceiling num) (- num (ceiling num))))))
  422. (define dylan:truncate (dylan::generic-fn 'truncate one-real #F))
  423. (add-method
  424. dylan:truncate
  425. (dylan::dylan-callable->method
  426. one-real
  427. (lambda (multiple-values next-method num)
  428. next-method
  429. (dylan-mv-call dylan:values multiple-values
  430. (truncate num) (- num (truncate num))))))
  431. (define dylan:round (dylan::generic-fn 'round one-real #F))
  432. (add-method
  433. dylan:round
  434. (dylan::dylan-callable->method
  435. one-real
  436. (lambda (multiple-values next-method num)
  437. next-method
  438. (dylan-mv-call dylan:values multiple-values
  439. (round num) (- num (round num))))))
  440. (define dylan:floor/ (dylan::generic-fn 'floor/ two-reals #F))
  441. (add-method
  442. dylan:floor/
  443. (dylan::dylan-callable->method
  444. two-reals
  445. (lambda (multiple-values next-method real1 real2)
  446. next-method
  447. (let ((floor-div-result (floor (/ real1 real2))))
  448. (dylan-mv-call dylan:values multiple-values
  449. floor-div-result
  450. (- real1 (* real2 floor-div-result)))))))
  451. (define dylan:ceiling/ (dylan::generic-fn 'ceiling/ two-reals #F))
  452. (add-method
  453. dylan:ceiling/
  454. (dylan::dylan-callable->method
  455. two-reals
  456. (lambda (multiple-values next-method real1 real2)
  457. next-method
  458. (let ((ceiling-div-result (ceiling (/ real1 real2))))
  459. (dylan-mv-call dylan:values multiple-values
  460. ceiling-div-result
  461. (- real1 (* real2 ceiling-div-result)))))))
  462. (define dylan:truncate/ (dylan::generic-fn 'truncate/ two-reals #F))
  463. (add-method
  464. dylan:truncate/
  465. (dylan::dylan-callable->method
  466. two-reals
  467. (lambda (multiple-values next-method real1 real2)
  468. next-method
  469. (let ((truncate-div-result (truncate (/ real1 real2))))
  470. (dylan-mv-call dylan:values multiple-values
  471. truncate-div-result
  472. (- real1 (* real2 truncate-div-result)))))))
  473. (define dylan:round/ (dylan::generic-fn 'round/ two-reals #F))
  474. (add-method
  475. dylan:round/
  476. (dylan::dylan-callable->method
  477. two-reals
  478. (lambda (multiple-values next-method real1 real2)
  479. next-method
  480. (let ((round-div-result (round (/ real1 real2))))
  481. (dylan-mv-call dylan:values multiple-values
  482. round-div-result
  483. (- real1 (* real2 round-div-result)))))))
  484. (define dylan:add-method
  485. (let* ((params
  486. (make-param-list
  487. `((GENERIC-FUNCTION ,<generic-function>) (METHOD ,<method>))
  488. #F #F #F))
  489. (generic-function (dylan::generic-fn 'add-method params #F)))
  490. (add-method
  491. generic-function
  492. (dylan::make-method
  493. params
  494. (lambda (multiple-values next-method generic-function method)
  495. next-method ; Ignored
  496. (add-method generic-function method
  497. (lambda (new old)
  498. (dylan-mv-call dylan:values multiple-values new old))))))
  499. generic-function))
  500. (define dylan:shallow-copy
  501. (dylan::generic-fn 'shallow-copy
  502. one-object
  503. (lambda (obj)
  504. (dylan-call dylan:error
  505. "shallow-copy -- not specialized for this object type" obj))))
  506. (define dylan:binary-gcd
  507. (dylan::generic-fn 'binary-gcd two-integers gcd))
  508. (define dylan:binary-lcm
  509. (dylan::generic-fn 'binary-lcm two-integers lcm))
  510. (define dylan:denominator
  511. (dylan::generic-fn 'denominator one-real denominator))
  512. (define dylan:numerator
  513. (dylan::generic-fn 'numerator one-real numerator))
  514. (define dylan:angle
  515. (dylan::generic-fn 'angle one-number angle))
  516. (define dylan:magnitude
  517. (dylan::generic-fn 'magnitude one-number magnitude))
  518. (define dylan:imag-part
  519. (dylan::generic-fn 'imag-part one-number imag-part))
  520. (define dylan:real-part
  521. (dylan::generic-fn 'real-part one-number real-part))
  522. (define dylan:rationalize
  523. (dylan::generic-fn 'rationalize one-number rationalize))
  524. (define dylan:init-function
  525. (dylan::generic-fn 'init-function one-slot slot.init-function))
  526. (define dylan:init-keyword
  527. (dylan::generic-fn 'init-keyword one-slot slot.init-keyword))
  528. (define dylan:init-value
  529. (dylan::generic-fn 'init-value one-slot #F))
  530. (add-method
  531. dylan:init-value
  532. (dylan::dylan-callable->method
  533. one-slot
  534. (lambda (multiple-values next-method slot)
  535. next-method
  536. (if (slot.has-initial-value? slot)
  537. (dylan-mv-call dylan:values multiple-values
  538. (slot.init-value slot) #T)
  539. (dylan-mv-call dylan:values multiple-values #F #F)))))
  540. (define dylan:applicable-method?
  541. (dylan::generic-fn 'applicable-method?
  542. (make-param-list `((FN ,<function>)) #F #T #F)
  543. (lambda (fn . args)
  544. (cond
  545. ((dylan::generic-function? fn)
  546. (any? (lambda (method)
  547. (method-applicable? method args))
  548. (generic-function.methods fn)))
  549. ((dylan::method? fn)
  550. (method-applicable? fn args))
  551. (else #F)))))
  552. (define dylan:apply
  553. (dylan::generic-fn 'apply (make-param-list `((FN ,<function>)) #F #T #F) #F))
  554. (add-method
  555. dylan:apply
  556. (dylan::dylan-callable->method
  557. (make-param-list `((FN ,<function>)) #F #T #F)
  558. (lambda (multiple-values next-method fn . args)
  559. (dylan-full-apply fn multiple-values next-method
  560. (split-last
  561. args
  562. (lambda (early end)
  563. (append early
  564. (if (null? end)
  565. '()
  566. (iterate->list (lambda (x) x)
  567. (car end))))))))))
  568. (define dylan:as
  569. (dylan::generic-fn 'as
  570. (make-param-list `((CLASS ,<class>) (OBJECT ,<object>)) #F #F #F)
  571. (lambda (class obj)
  572. (if (dylan-call dylan:instance? obj class)
  573. obj
  574. (dylan-call dylan:error
  575. "as -- not specialized for this class type"
  576. class obj)))))
  577. (begin
  578. ;; integer <-> character
  579. (add-method dylan:as
  580. (dylan::function->method
  581. (make-param-list `((CLASS ,(dylan::make-singleton <integer>))
  582. (OBJECT ,<character>)) #F #F #F)
  583. (lambda (class object) class (char->integer object))))
  584. (add-method dylan:as
  585. (dylan::function->method
  586. (make-param-list `((CLASS ,(dylan::make-singleton <character>))
  587. (OBJECT ,<integer>)) #F #F #F)
  588. (lambda (class object) class (integer->char object))))
  589. ;; number conversions
  590. (define (no-change class object) class object)
  591. (define (->exact class object) class (inexact->exact object))
  592. (define (->inexact class object) class (exact->inexact object))
  593. (add-method dylan:as
  594. (dylan::function->method
  595. (make-param-list `((CLASS ,(dylan::make-singleton <number>))
  596. (OBJECT ,<number>)) #F #F #F)
  597. no-change))
  598. (add-method dylan:as
  599. (dylan::function->method
  600. (make-param-list `((CLASS ,(dylan::make-singleton <complex>))
  601. (OBJECT ,<number>)) #F #F #F)
  602. no-change))
  603. (add-method dylan:as
  604. (dylan::function->method
  605. (make-param-list `((CLASS ,(dylan::make-singleton <real>))
  606. (OBJECT ,<real>)) #F #F #F)
  607. no-change))
  608. (add-method dylan:as
  609. (dylan::function->method
  610. (make-param-list `((CLASS ,(dylan::make-singleton <rectangular-complex>))
  611. (OBJECT ,<number>)) #F #F #F)
  612. no-change))
  613. (add-method dylan:as
  614. (dylan::function->method
  615. (make-param-list `((CLASS ,(dylan::make-singleton <rational>))
  616. (OBJECT ,<number>)) #F #F #F)
  617. ->exact))
  618. (add-method dylan:as
  619. (dylan::function->method
  620. (make-param-list `((CLASS ,(dylan::make-singleton <float>))
  621. (OBJECT ,<number>)) #F #F #F)
  622. ->inexact))
  623. (add-method dylan:as
  624. (dylan::function->method
  625. (make-param-list `((CLASS ,(dylan::make-singleton <integer>))
  626. (OBJECT ,<number>)) #F #F #F)
  627. ->exact))
  628. (add-method dylan:as
  629. (dylan::function->method
  630. (make-param-list `((CLASS ,(dylan::make-singleton <ratio>))
  631. (OBJECT ,<number>)) #F #F #F)
  632. ->exact))
  633. (add-method dylan:as
  634. (dylan::function->method
  635. (make-param-list `((CLASS ,(dylan::make-singleton <single-float>))
  636. (OBJECT ,<number>)) #F #F #F)
  637. ->inexact))
  638. (add-method dylan:as
  639. (dylan::function->method
  640. (make-param-list `((CLASS ,(dylan::make-singleton <double-float>))
  641. (OBJECT ,<number>)) #F #F #F)
  642. ->inexact))
  643. (add-method dylan:as
  644. (dylan::function->method
  645. (make-param-list `((CLASS ,(dylan::make-singleton <extended-float>))
  646. (OBJECT ,<number>)) #F #F #F)
  647. ->inexact))
  648. ; symbols, strings, and keywords
  649. (add-method dylan:as
  650. (dylan::function->method
  651. (make-param-list `((CLASS ,(dylan::make-singleton <string>))
  652. (SYMBOL ,<symbol>)) #F #F #F)
  653. (lambda (class symbol)
  654. class ; Unused
  655. (symbol->string symbol))))
  656. (add-method dylan:as
  657. (dylan::function->method
  658. (make-param-list `((CLASS ,(dylan::make-singleton <string>))
  659. (KEYWORD ,<keyword>)) #F #F #F)
  660. (lambda (class keyword)
  661. class ; Unused
  662. (let ((string (symbol->string keyword)))
  663. (substring string 0 (- (string-length string) 1))))))
  664. (add-method dylan:as
  665. (dylan::function->method
  666. (make-param-list `((CLASS ,(dylan::make-singleton <symbol>))
  667. (STRING ,<string>)) #F #F #F)
  668. (lambda (class string)
  669. class ; Unused
  670. (new-name "" string ""))))
  671. (add-method dylan:as
  672. (dylan::function->method
  673. (make-param-list `((CLASS ,(dylan::make-singleton <keyword>))
  674. (STRING ,<string>)) #F #F #F)
  675. (lambda (class string)
  676. class ; Unused
  677. (new-name "" string ":"))))
  678. )
  679. (define dylan:complement
  680. (dylan::function->method
  681. one-function
  682. (lambda (fn)
  683. (make-dylan-callable
  684. (lambda args
  685. (not (dylan-apply fn args)))))))
  686. (define dylan:compose
  687. (dylan::function->method
  688. at-least-one-function
  689. (lambda (fn . rest-fns)
  690. (if (null? rest-fns)
  691. fn
  692. (lambda (multiple-values next-method . args)
  693. (define (compose fn rest-fns)
  694. (if (null? rest-fns)
  695. (dylan-apply fn args)
  696. (dylan-call fn (compose (car rest-fns) (cdr rest-fns)))))
  697. next-method ; Not used
  698. (dylan-mv-call fn multiple-values
  699. (compose (car rest-fns) (cdr rest-fns))))))))
  700. (define dylan:disjoin
  701. (dylan::function->method
  702. at-least-one-function
  703. (lambda (fn . rest-fns)
  704. (if (null? rest-fns)
  705. fn
  706. (lambda (multiple-values next-method . args)
  707. next-method
  708. (let loop ((fn fn)
  709. (rest-fns rest-fns))
  710. (if (null? rest-fns)
  711. (dylan-mv-apply fn multiple-values args)
  712. (let ((value (dylan-apply fn args)))
  713. (if value
  714. value
  715. (loop (car rest-fns) (cdr rest-fns)))))))))))
  716. (define dylan:conjoin
  717. (dylan::function->method
  718. at-least-one-function
  719. (lambda (fn . rest-fns)
  720. (if (null? rest-fns)
  721. fn
  722. (lambda (multiple-values next-method . args)
  723. next-method
  724. (let loop ((fn fn)
  725. (rest-fns rest-fns))
  726. (if (null? rest-fns)
  727. (dylan-mv-apply fn multiple-values args)
  728. (if (dylan-apply fn args)
  729. (loop (car rest-fns) (cdr rest-fns))
  730. #F))))))))
  731. (define dylan:curry
  732. (dylan::function->method
  733. function-and-arguments
  734. (lambda (fn . curried-args)
  735. (lambda (multiple-values next-method . args)
  736. next-method
  737. (dylan-mv-apply fn multiple-values (append curried-args args))))))
  738. (define dylan:rcurry
  739. (dylan::function->method
  740. function-and-arguments
  741. (lambda (fn . curried-args)
  742. (lambda (multiple-values next-method . args)
  743. next-method
  744. (dylan-mv-apply fn multiple-values (append args curried-args))))))