PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/runtime-collections-generic2.scm

http://github.com/pablomarx/Thomas
Scheme | 673 lines | 571 code | 55 blank | 47 comment | 4 complexity | 97be101945fcf04371a6c1ada4fe7f81 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-collections-generic2.scm,v 1.1 1992/09/18 23:45:58 birkholz Exp $
  38. ;;; This file is a continuation of runtime-collections-generic, which had
  39. ;;; to be split because of a limitation in the Gambit compiler.
  40. ;;;;
  41. ;;;; FUNCTIONS FOR SEQUENCES (page 104)
  42. ;;;;
  43. (define dylan:add
  44. (dylan::generic-fn 'add one-sequence-and-an-object
  45. (lambda rest
  46. (dylan-call dylan:error
  47. "add -- generic method not specialized for this collection"
  48. rest))))
  49. (define dylan:add!
  50. (dylan::generic-fn 'add!
  51. one-sequence-and-an-object
  52. (lambda (seq obj)
  53. (dylan-call dylan:add seq obj)))) ; Defaults to ADD
  54. (define dylan:add-new
  55. (dylan::generic-fn
  56. 'add-new
  57. (make-param-list `((SEQUENCE ,<sequence>) (OBJECT ,<object>))
  58. #F #F '(test:))
  59. #F))
  60. (add-method
  61. dylan:add-new
  62. (dylan::dylan-callable->method
  63. (make-param-list `((SEQUENCE ,<sequence>) (OBJECT ,<object>))
  64. #F #F '(test:))
  65. (lambda (multiple-values next-method seq object . rest)
  66. multiple-values
  67. (dylan::keyword-validate next-method rest '(test:))
  68. (let ((test-fn (dylan::find-keyword rest 'test:
  69. (lambda () dylan:id?))))
  70. (if (iterate-until (lambda (x) (dylan-call test-fn x object)) seq)
  71. seq
  72. (dylan-call dylan:add seq object))))))
  73. (define dylan:add-new!
  74. (dylan::generic-fn
  75. 'add-new
  76. (make-param-list `((SEQUENCE ,<sequence>) (OBJECT ,<object>))
  77. #F #F '(test:))
  78. #F))
  79. (add-method
  80. dylan:add-new!
  81. (dylan::dylan-callable->method
  82. (make-param-list `((SEQUENCE ,<sequence>) (OBJECT ,<object>))
  83. #F #F '(test:))
  84. (lambda (multiple-values next-method seq object . rest)
  85. multiple-values
  86. (dylan::keyword-validate next-method rest '(test:))
  87. (let ((test-fn (dylan::find-keyword rest 'test:
  88. (lambda () dylan:id?))))
  89. (if (iterate-until (lambda (x) (dylan-call test-fn x object)) seq)
  90. seq
  91. (dylan-call dylan:add! seq object))))))
  92. (define dylan:remove
  93. (dylan::generic-fn
  94. 'remove
  95. (make-param-list `((SEQUENCE ,<sequence>) (VALUE ,<object>))
  96. #F #F '(test: count:))
  97. #F))
  98. (add-method
  99. dylan:remove
  100. (dylan::dylan-callable->method
  101. (make-param-list `((SEQUENCE ,<sequence>) (VALUE ,<object>))
  102. #F #F '(test: count:))
  103. (lambda (multiple-values next-method seq value . rest)
  104. multiple-values
  105. (dylan::keyword-validate next-method rest '(test: count:))
  106. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:id?)))
  107. (count (dylan::find-keyword rest 'count: (lambda () -1))))
  108. (let loop ((state (dylan-call dylan:initial-state seq))
  109. (result (dylan-call dylan:make
  110. (dylan-call dylan:class-for-copy seq)))
  111. (changed 0))
  112. (if state
  113. (let ((cur-element (dylan-call dylan:current-element seq state)))
  114. (if (and (or (negative? count)
  115. (< changed count))
  116. (dylan-call test? cur-element value))
  117. (loop (dylan-call dylan:next-state seq state)
  118. result
  119. (+ changed 1))
  120. (loop (dylan-call dylan:next-state seq state)
  121. (dylan-call dylan:add result cur-element)
  122. changed)))
  123. (dylan-call dylan:reverse result)))))))
  124. (define dylan:remove!
  125. (dylan::generic-fn
  126. 'remove!
  127. (make-param-list `((SEQUENCE ,<sequence>) (VALUE ,<object>))
  128. #F #F '(test: count:))
  129. #F))
  130. (add-method
  131. dylan:remove!
  132. (dylan::dylan-callable->method
  133. (make-param-list `((SEQUENCE ,<sequence>) (VALUE ,<object>))
  134. #F #F '(test: count:))
  135. (lambda (multiple-values next-method seq value . rest)
  136. multiple-values
  137. (dylan::keyword-validate next-method rest '(test: count:))
  138. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:id?)))
  139. (count (dylan::find-keyword
  140. rest 'count:
  141. (lambda () (dylan-call dylan:size seq)))))
  142. (dylan-call dylan:remove seq value 'test: test? 'count: count)))))
  143. (define dylan:choose
  144. (dylan::generic-fn 'choose
  145. (make-param-list `((PREDICATE ,<function>) (SEQUENCE ,<sequence>)) #F #F #F)
  146. (lambda (test? seq)
  147. (let loop ((state (dylan-call dylan:initial-state seq))
  148. (result (dylan-call dylan:make
  149. (dylan-call dylan:class-for-copy seq))))
  150. (if state
  151. (let ((cur-element (dylan-call dylan:current-element seq state)))
  152. (loop (dylan-call dylan:next-state seq state)
  153. (if (dylan-call test? cur-element)
  154. (dylan-call dylan:add result cur-element)
  155. result)))
  156. (dylan-call dylan:reverse result))))))
  157. (define dylan:choose-by
  158. (dylan::generic-fn 'choose-by
  159. (make-param-list `((PREDICATE ,<function>)
  160. (TEST-SEQUENCE ,<sequence>)
  161. (VALUE-SEQUENCE ,<sequence>)) #F #F #F)
  162. (lambda (test? test-sequence value-sequence)
  163. (let loop ((test-state (dylan-call dylan:initial-state test-sequence))
  164. (value-state (dylan-call dylan:initial-state value-sequence))
  165. (result (dylan-call dylan:make
  166. (dylan-call dylan:class-for-copy
  167. value-sequence))))
  168. (if (and test-state value-state)
  169. (let ((test-element
  170. (dylan-call dylan:current-element
  171. test-sequence test-state)))
  172. (loop (dylan-call dylan:next-state test-sequence test-state)
  173. (dylan-call dylan:next-state value-sequence value-state)
  174. (if (dylan-call test? test-element)
  175. (dylan-call dylan:add
  176. result
  177. (dylan-call dylan:current-element
  178. value-sequence value-state))
  179. result)))
  180. (dylan-call dylan:reverse result))))))
  181. (define dylan:intersection
  182. ;; Does intersection result in a set whose elements are unique?
  183. ;; This implementation may result in a multi-set...
  184. (dylan::generic-fn
  185. 'intersection
  186. (make-param-list `((SEQUENCE-1 ,<sequence>) (SEQUENCE-2 ,<sequence>))
  187. #F #F '(test:))
  188. #F))
  189. (add-method
  190. dylan:intersection
  191. (dylan::dylan-callable->method
  192. (make-param-list `((SEQUENCE-1 ,<sequence>) (SEQUENCE-2 ,<sequence>))
  193. #F #F '(test:))
  194. (lambda (multiple-values next-method seq-1 seq-2 . rest)
  195. multiple-values
  196. (dylan::keyword-validate next-method rest '(test:))
  197. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:id?))))
  198. (let loop ((state (dylan-call dylan:initial-state seq-1))
  199. (result (dylan-call
  200. dylan:make
  201. (dylan-call dylan:class-for-copy seq-1))))
  202. (if state
  203. (let ((a (dylan-call dylan:current-element seq-1 state)))
  204. (loop (dylan-call dylan:next-state seq-1 state)
  205. (if (dylan-call
  206. dylan:any?
  207. (make-dylan-callable (lambda (b)
  208. (dylan-call test? a b))
  209. 1)
  210. seq-2)
  211. (dylan-call dylan:add result a)
  212. result)))
  213. (dylan-call dylan:reverse result)))))))
  214. (define dylan:union
  215. (dylan::generic-fn
  216. 'union
  217. (make-param-list
  218. `((SEQUENCE-1 ,<sequence>) (SEQUENCE-2 ,<sequence>)) #F #F '(test:))
  219. #F))
  220. (add-method
  221. dylan:union
  222. (dylan::dylan-callable->method
  223. (make-param-list
  224. `((SEQUENCE-1 ,<sequence>) (SEQUENCE-2 ,<sequence>)) #F #F '(test:))
  225. (lambda (multiple-values next-method seq-1 seq-2 . rest)
  226. multiple-values ; Ignored
  227. (dylan::keyword-validate next-method rest '(test:))
  228. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:id?))))
  229. (dylan-call dylan:remove-duplicates
  230. (dylan-call dylan:concatenate
  231. (dylan-call dylan:as
  232. (dylan-call dylan:class-for-copy
  233. seq-1)
  234. seq-1)
  235. (dylan-call dylan:as
  236. (dylan-call dylan:class-for-copy
  237. seq-1)
  238. seq-2))
  239. 'test: test?)))))
  240. (define dylan:remove-duplicates
  241. (dylan::generic-fn
  242. 'remove-duplicates
  243. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test:))
  244. #F))
  245. (add-method
  246. dylan:remove-duplicates
  247. (dylan::dylan-callable->method
  248. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test:))
  249. (lambda (multiple-values next-method seq . rest)
  250. multiple-values
  251. (dylan::keyword-validate next-method rest '(test:))
  252. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:id?))))
  253. (let loop ((state (dylan-call dylan:initial-state seq))
  254. (result (dylan-call dylan:make
  255. (dylan-call dylan:class-for-copy seq))))
  256. (if state
  257. (let ((cur-element (dylan-call dylan:current-element seq state))
  258. (result-size (dylan-call dylan:size result)))
  259. (do ((state-2 (dylan-call dylan:initial-state seq)
  260. (dylan-call dylan:next-state seq state-2))
  261. (count 0 (+ count 1)))
  262. ((or (>= count result-size)
  263. (dylan-call test?
  264. cur-element
  265. (dylan-call dylan:current-element
  266. seq state-2)))
  267. (loop (dylan-call dylan:next-state seq state)
  268. (if (>= count result-size)
  269. (dylan-call dylan:add result cur-element)
  270. result)))))
  271. (dylan-call dylan:reverse result)))))))
  272. (define dylan:remove-duplicates!
  273. (dylan::generic-fn
  274. 'remove-duplicates!
  275. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test:))
  276. #F))
  277. (add-method
  278. dylan:remove-duplicates!
  279. (dylan::dylan-callable->method
  280. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test:))
  281. (lambda (multiple-values next-method seq . rest)
  282. multiple-values
  283. (dylan::keyword-validate next-method rest '(test:))
  284. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:id?))))
  285. (dylan-call dylan:remove-duplicates seq 'test: test?)))))
  286. (define dylan:copy-sequence
  287. (dylan::generic-fn
  288. 'copy-sequence
  289. (make-param-list `((SOURCE ,<sequence>)) #F #F '(start: end:))
  290. #F))
  291. (add-method
  292. dylan:copy-sequence
  293. (dylan::dylan-callable->method
  294. (make-param-list `((SOURCE ,<sequence>)) #F #F '(start: end:))
  295. (lambda (multiple-values next-method source . rest)
  296. multiple-values
  297. (dylan::keyword-validate next-method rest '(start: end:))
  298. (let ((start (dylan::find-keyword rest 'start: (lambda () 0)))
  299. (end (dylan::find-keyword
  300. rest 'end: (lambda () (dylan-call dylan:size source)))))
  301. (let loop ((state (dylan-call dylan:initial-state source))
  302. (result (dylan-call dylan:make
  303. (dylan-call
  304. dylan:class-for-copy source)))
  305. (index 0))
  306. (if (and state (<= index (- end 1)))
  307. (loop (dylan-call dylan:next-state source state)
  308. (if (>= index start)
  309. (dylan-call dylan:add
  310. result
  311. (dylan-call dylan:current-element
  312. source state))
  313. result)
  314. (+ index 1))
  315. (dylan-call dylan:reverse result)))))))
  316. (define dylan:concatenate-as
  317. (dylan::generic-fn 'concatenate-as
  318. (make-param-list `((CLASS ,<class>) (SEQUENCE ,<sequence>)) #F 'REST #F)
  319. (lambda (class seq-1 . rest)
  320. (if (not (subclass? class <mutable-sequence>))
  321. (dylan-call dylan:error
  322. "concatenate-as -- target class not a mutable sequence"
  323. class seq-1 rest))
  324. (dylan-call dylan:as
  325. class (dylan-call dylan:apply
  326. dylan:concatenate (cons seq-1 rest))))))
  327. (define dylan:concatenate
  328. (dylan::generic-fn 'concatenate
  329. at-least-one-sequence
  330. (lambda (seq-1 . rest)
  331. (dylan-call dylan:error
  332. "concatenate -- not specialized for argument" seq-1 rest))))
  333. (define dylan:replace-subsequence!
  334. (dylan::generic-fn
  335. 'replace-subsequence!
  336. (make-param-list `((MUTABLE-SEQUENCE ,<mutable-sequence>)
  337. (INSERT-SEQUENCE ,<sequence>))
  338. #F #F '(start:))
  339. #F))
  340. (add-method
  341. dylan:replace-subsequence!
  342. (dylan::dylan-callable->method
  343. (make-param-list `((MUTABLE-SEQUENCE ,<mutable-sequence>)
  344. (INSERT-SEQUENCE ,<sequence>))
  345. #F #F '(start:))
  346. (lambda (multiple-values next-method mutable insert . rest)
  347. multiple-values
  348. (dylan::keyword-validate next-method rest '(start:))
  349. (let ((start (dylan::find-keyword rest 'start: (lambda () 0)))
  350. (m-state (dylan-call dylan:initial-state mutable)))
  351. (if (< (- (dylan-call dylan:size mutable) start)
  352. (dylan-call dylan:size insert))
  353. (dylan-call dylan:error
  354. "replace-subsequence! -- not enough elements in target"
  355. mutable insert start))
  356. (if (negative? start)
  357. (dylan-call dylan:error
  358. "replace-subsequence! -- index cannot be negative"
  359. mutable insert start))
  360. (do ((count 0 (+ count 1)))
  361. ((= count start) 'done)
  362. (set! m-state (dylan-call dylan:next-state mutable m-state)))
  363. (let loop ((i-state (dylan-call dylan:initial-state insert))
  364. (m-state m-state))
  365. (if i-state
  366. (begin
  367. (dylan-call
  368. dylan:setter/current-element/
  369. mutable m-state
  370. (dylan-call dylan:current-element insert i-state))
  371. (loop (dylan-call dylan:next-state insert i-state)
  372. (dylan-call dylan:next-state mutable m-state)))
  373. mutable))))))
  374. (define dylan:reverse
  375. (dylan::generic-fn 'reverse
  376. one-sequence
  377. (lambda (seq-1)
  378. (dylan-call dylan:error
  379. "reverse -- not defined for this sequence type" seq-1))))
  380. (define dylan:reverse!
  381. (dylan::generic-fn 'reverse!
  382. one-sequence
  383. (lambda (seq-1)
  384. (dylan-call dylan:reverse seq-1))))
  385. (define dylan:sort
  386. (dylan::generic-fn
  387. 'sort
  388. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test: stable:))
  389. #F))
  390. (add-method
  391. dylan:sort
  392. (dylan::dylan-callable->method
  393. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test: stable:))
  394. (lambda (multiple-values next-method seq . rest)
  395. multiple-values
  396. (dylan::keyword-validate next-method rest '(test: stable:))
  397. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:<)))
  398. (stable (dylan::find-keyword rest 'stable: (lambda () #F))))
  399. stable ; Ignored
  400. (dylan-call dylan:as
  401. (dylan-call dylan:class-for-copy seq)
  402. (sort (dylan-call dylan:as <list> seq)
  403. (lambda (x y)
  404. (dylan-call test? x y))))))))
  405. (define dylan:sort!
  406. (dylan::generic-fn
  407. 'sort!
  408. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test: stable:))
  409. #F))
  410. (add-method
  411. dylan:sort!
  412. (dylan::dylan-callable->method
  413. (make-param-list `((SEQUENCE ,<sequence>)) #F #F '(test: stable:))
  414. (lambda (multiple-values next-method seq . rest)
  415. multiple-values
  416. (dylan::keyword-validate next-method rest '(test: stable:))
  417. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:<)))
  418. (stable (dylan::find-keyword rest 'stable: (lambda () #F))))
  419. (dylan-call dylan:sort seq 'test: test? 'stable: stable)))))
  420. (define dylan:first
  421. (dylan::generic-fn 'first
  422. one-sequence
  423. (lambda (sequence-1)
  424. (let ((state (dylan-call dylan:initial-state sequence-1)))
  425. (if state
  426. (dylan-call dylan:current-element sequence-1 state)
  427. (dylan-call dylan:error
  428. "first -- no element in sequence" sequence-1))))))
  429. (define dylan:second
  430. (dylan::generic-fn 'second
  431. one-sequence
  432. (lambda (sequence-1)
  433. (let ((state (dylan-call dylan:get-state sequence-1 1)))
  434. (if state
  435. (dylan-call dylan:current-element sequence-1 state)
  436. (dylan-call dylan:error
  437. "second -- sequence size < 2" sequence-1))))))
  438. (define dylan:third
  439. (dylan::generic-fn 'third
  440. one-sequence
  441. (lambda (sequence-1)
  442. (let ((state (dylan-call dylan:get-state sequence-1 2)))
  443. (if state
  444. (dylan-call dylan:current-element sequence-1 state)
  445. (dylan-call dylan:error
  446. "third -- sequence size < 3" sequence-1))))))
  447. (define dylan:setter/first/
  448. (dylan::generic-fn 'setter/first/
  449. one-mutable-sequence-and-an-object
  450. (lambda (sequence-1 new-value)
  451. (let ((state (dylan-call dylan:initial-state sequence-1)))
  452. (if state
  453. (begin
  454. (dylan-call
  455. dylan:setter/current-element/ sequence-1 state new-value)
  456. new-value)
  457. (dylan-call dylan:error
  458. "(setter first) -- sequence is empty"
  459. sequence-1 new-value))))))
  460. (define dylan:setter/second/
  461. (dylan::generic-fn 'setter/first/
  462. one-mutable-sequence-and-an-object
  463. (lambda (sequence-1 new-value)
  464. (let ((size (dylan-call dylan:size sequence-1)))
  465. (if (or (not size) (>= size 2))
  466. (begin
  467. (dylan-call dylan:setter/current-element/
  468. sequence-1
  469. (dylan-call dylan:get-state sequence-1 1)
  470. new-value)
  471. new-value)
  472. (dylan-call dylan:error
  473. "(setter second) -- sequence size < 2"
  474. sequence-1 new-value))))))
  475. (define dylan:setter/third/
  476. (dylan::generic-fn 'setter/first/
  477. one-mutable-sequence-and-an-object
  478. (lambda (sequence-1 new-value)
  479. (let ((size (dylan-call dylan:size sequence-1)))
  480. (if (or (not size) (>= size 3))
  481. (begin
  482. (dylan-call dylan:setter/current-element/
  483. sequence-1
  484. (dylan-call dylan:get-state sequence-1 2)
  485. new-value)
  486. new-value)
  487. (dylan-call dylan:error
  488. "(setter third) -- sequence size < 3"
  489. sequence-1 new-value))))))
  490. (define dylan:last
  491. (dylan::generic-fn 'last
  492. one-sequence
  493. (lambda (sequence-1)
  494. (let ((prev-state #F))
  495. (do ((state (dylan-call dylan:initial-state sequence-1)
  496. (dylan-call dylan:next-state sequence-1 state)))
  497. ((not state)
  498. (if prev-state
  499. (dylan-call dylan:current-element sequence-1 prev-state)
  500. (dylan-call dylan:error
  501. "last -- sequence is empty" sequence-1)))
  502. (set! prev-state state))))))
  503. (define (check-subsequence test? big big-state pattern pattern-state)
  504. (define (check-loop big-state pattern-state)
  505. (if (not pattern-state)
  506. #T
  507. (if (and big-state
  508. (dylan-call test?
  509. (dylan-call dylan:current-element big big-state)
  510. (dylan-call dylan:current-element pattern pattern-state)))
  511. (check-loop
  512. (dylan-call dylan:next-state big big-state)
  513. (dylan-call dylan:next-state pattern pattern-state))
  514. #F)))
  515. (check-loop (dylan-call dylan:copy-state big big-state)
  516. (dylan-call dylan:copy-state pattern pattern-state)))
  517. (define dylan:subsequence-position
  518. (dylan::generic-fn
  519. 'subsequence-position
  520. (make-param-list
  521. `((BIG ,<sequence>) (PATTERN ,<sequence>)) #F #F '(test: count:))
  522. #F))
  523. (add-method
  524. dylan:subsequence-position
  525. (dylan::dylan-callable->method
  526. (make-param-list
  527. `((BIG ,<sequence>) (PATTERN ,<sequence>)) #F #F '(test: count:))
  528. (lambda (multiple-values next-method big pattern . rest)
  529. multiple-values
  530. (dylan::keyword-validate next-method rest '(test: count:))
  531. (let ((test? (dylan::find-keyword rest 'test: (lambda () dylan:id?)))
  532. (count (dylan::find-keyword rest 'count: (lambda () 1)))
  533. (first-of-pattern (dylan-call dylan:first pattern))
  534. (init-state-pattern (dylan-call dylan:initial-state pattern)))
  535. (let loop ((state (dylan-call dylan:initial-state big))
  536. (num-found 0)
  537. (index 0))
  538. (if state
  539. (if (and (dylan-call test?
  540. (dylan-call dylan:current-element big state)
  541. first-of-pattern)
  542. (check-subsequence test? big state
  543. pattern init-state-pattern))
  544. (if (>= num-found (- count 1))
  545. index
  546. (loop (dylan-call dylan:next-state big state)
  547. (+ num-found 1)
  548. (+ index 1)))
  549. (loop (dylan-call dylan:next-state big state)
  550. num-found
  551. (+ index 1)))
  552. #F)))))) ; not found
  553. ;;;;
  554. ;;;; MUTABLE COLLECTIONS (p. 127)
  555. ;;;;
  556. (define dylan:setter/current-element/
  557. (dylan::generic-fn 'setter/current-element/
  558. (make-param-list `((MUTABLE-COLLECTION ,<mutable-collection>)
  559. (STATE ,<object>)
  560. (NEW-VALUE ,<object>))
  561. #F #F #F)
  562. (lambda (mutable-collection state new-value)
  563. (dylan-call dylan:error
  564. "(setter current-element) -- cannot set! this collection type"
  565. mutable-collection state new-value))))
  566. (define dylan:setter/element/
  567. (dylan::generic-fn 'setter/element/
  568. (make-param-list `((MUTABLE-COLLECTION ,<mutable-collection>)
  569. (KEY ,<object>)
  570. (NEW-VAL ,<object>))
  571. #F #F #F)
  572. (lambda (collection key new-value)
  573. (dylan-call dylan:error
  574. "(setter element) -- not defined for this collection type"
  575. collection key new-value))))
  576. (add-method dylan:setter/element/
  577. (dylan::function->method
  578. (make-param-list `((MUTABLE-SEQUENCE ,<mutable-sequence>)
  579. (KEY ,<integer>)
  580. (NEW-VALUE ,<object>))
  581. #F #F #F)
  582. (lambda (mut-seq key new-value)
  583. (do ((state (dylan-call dylan:initial-state mut-seq)
  584. (dylan-call dylan:next-state mut-seq state))
  585. (k 0 (+ k 1)))
  586. ((or (not state) (= k key))
  587. (if state
  588. (begin
  589. (dylan-call dylan:setter/current-element/
  590. mut-seq state new-value)
  591. new-value)
  592. (dylan-call dylan:error
  593. "(setter element) -- key not found"
  594. mut-seq key new-value)))))))
  595. (add-method dylan:setter/element/
  596. (dylan::function->method
  597. (make-param-list
  598. `((MUTABLE-EXPLICIT-KEY-COLLECTION ,<mutable-explicit-key-collection>)
  599. (KEY ,<object>)
  600. (NEW-VALUE ,<object>))
  601. #F #F #F)
  602. (lambda (mut-seq key new-value)
  603. (do ((state (dylan-call dylan:initial-state mut-seq)
  604. (dylan-call dylan:next-state mut-seq state)))
  605. ((or (not state) (dylan-call
  606. dylan:=
  607. (dylan-call dylan:current-key mut-seq state)
  608. key))
  609. (if state
  610. (begin
  611. (dylan-call dylan:setter/current-element/
  612. mut-seq state new-value)
  613. new-value)
  614. (dylan-call dylan:error
  615. "(setter element) -- key not found"
  616. mut-seq key new-value)))))))