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

/src/runtime-collections-array.scm

http://github.com/pablomarx/Thomas
Scheme | 334 lines | 262 code | 20 blank | 52 comment | 0 complexity | e95b13e50f4d9b4aedd5a4308f528344 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-array.scm,v 1.17 1992/09/08 11:15:05 birkholz Exp $
  38. ;;;;; RUNTIME-COLLECTIONS-ARRAY.SCM
  39. ;;;;; This file contains all the specializations for array type
  40. (add-method dylan:shallow-copy
  41. (dylan::function->method
  42. (make-param-list `((ARRAY ,<array>)) #F #F #F)
  43. (lambda (array)
  44. (let* ((dimensions (dylan-call dylan:dimensions array))
  45. (new-array
  46. (dylan-call dylan:make <array> 'dimensions: dimensions))
  47. (key-sequence (dylan-call dylan:key-sequence array)))
  48. (do ((state (dylan-call dylan:initial-state key-sequence)
  49. (dylan-call dylan:next-state key-sequence state)))
  50. ((not state)
  51. (dylan-call dylan:as
  52. (dylan-call dylan:class-for-copy array)
  53. new-array))
  54. (let ((key (dylan-call dylan:current-element key-sequence state)))
  55. (dylan-call dylan:setter/element/
  56. new-array
  57. key
  58. (dylan-call dylan:element array key))))))))
  59. (add-method dylan:as
  60. (dylan::function->method
  61. (make-param-list `((CLASS ,(dylan::make-singleton <array>))
  62. (COLLECTION ,<collection>)) #F #F #F)
  63. (lambda (class collection)
  64. class
  65. (if (dylan-call dylan:instance? collection <array>)
  66. collection
  67. (let* ((size (dylan-call dylan:size collection))
  68. (new-array
  69. (dylan-call dylan:make <array> 'dimensions: (list size)))
  70. (vector-value (dylan-call dylan:get-array-value new-array)))
  71. (do ((state (dylan-call dylan:initial-state collection)
  72. (dylan-call dylan:next-state collection state))
  73. (index 0 (+ index 1)))
  74. ((not state) new-array)
  75. (vector-set! vector-value index
  76. (dylan-call
  77. dylan:current-element collection state))))))))
  78. ;;;
  79. ;;; ARRAY SPECIALIZED MAKE
  80. ;;;
  81. ;; All subclasses of ARRAY have slots for the data ("value") and a
  82. ;; list of dimensions ("dimensions").
  83. (define dylan:get-array-value "define dylan:get-array-value")
  84. (define dylan:get-array-dimensions "define dylan:get-array-dimensions")
  85. (define dylan:set-array-value! "define dylan:set-array-value!")
  86. (define dylan:set-array-dimensions! "define dylan:set-array-dimensions!")
  87. (create-private-slot <array> <simple-object-vector>
  88. "internal-array-value"
  89. (lambda (set get)
  90. (set! dylan:set-array-value! set)
  91. (set! dylan:get-array-value get)))
  92. (create-private-slot <array> <list>
  93. "internal-array-dimensions"
  94. (lambda (set get)
  95. (set! dylan:set-array-dimensions! set)
  96. (set! dylan:get-array-dimensions get)))
  97. ;; These four generic operations must be specialized for the special
  98. ;; cases of <byte-string> and <simple-object-vector>
  99. (add-method dylan:get-array-value
  100. (one-arg 'STRING <byte-string> (lambda (string) string)))
  101. (add-method dylan:set-array-value!
  102. (dylan::function->method
  103. (make-param-list `((STRING ,<byte-string>) (VALUE ,<object>)) #F #F #F)
  104. (lambda (string value)
  105. (dylan-call dylan:error
  106. "set-array-value! -- internal error on string"
  107. string value))))
  108. (add-method dylan:get-array-dimensions
  109. (one-arg 'STRING <byte-string>
  110. (lambda (string) (list (string-length string)))))
  111. (add-method dylan:set-array-dimensions!
  112. (dylan::function->method
  113. (make-param-list `((STRING ,<byte-string>) (VALUE ,<object>)) #F #F #F)
  114. (lambda (string value)
  115. (dylan-call dylan:error
  116. "set-array-dimensions! -- internal error on string"
  117. string value))))
  118. (add-method dylan:get-array-value
  119. (one-arg 'VECTOR <simple-object-vector>
  120. (lambda (vector) vector)))
  121. (add-method dylan:set-array-value!
  122. (dylan::function->method
  123. (make-param-list `((VECTOR ,<simple-object-vector>)
  124. (VALUE ,<object>)) #F #F #F)
  125. (lambda (vector value)
  126. (dylan-call dylan:error
  127. "set-array-value! -- internal error on simple-object-vector"
  128. vector value))))
  129. (add-method dylan:get-array-dimensions
  130. (one-arg 'VECTOR <simple-object-vector>
  131. (lambda (vector) (list (vector-length vector)))))
  132. (add-method dylan:set-array-dimensions!
  133. (dylan::function->method
  134. (make-param-list `((VECTOR ,<simple-object-vector>)
  135. (VALUE ,<object>)) #F #F #F)
  136. (lambda (vector value)
  137. (dylan-call
  138. dylan:error
  139. "set-array-dimensions! -- internal error on simple-object-vector"
  140. vector value))))
  141. (add-method
  142. dylan:make
  143. (dylan::dylan-callable->method
  144. (make-param-list `((ARRAY ,(dylan::make-singleton <array>)))
  145. #F #F '(dimensions: fill:))
  146. (lambda (multiple-values next-method class . rest)
  147. (define (make-multi-dimensional-array dimensions fill)
  148. (if (null? dimensions)
  149. (dylan-call dylan:error
  150. "make -- 0-dimensional arrays not allowed"))
  151. (let ((result (make-vector (car dimensions) fill)))
  152. (if (null? (cdr dimensions))
  153. result
  154. (do ((n 0 (+ n 1)))
  155. ((= n (car dimensions)) result)
  156. (vector-set! result n
  157. (make-multi-dimensional-array
  158. (cdr dimensions)
  159. fill))))))
  160. multiple-values ; Ignored
  161. class ; Ignored
  162. (dylan::keyword-validate next-method rest '(dimensions: fill:))
  163. (let ((dimensions
  164. (dylan::find-keyword rest 'dimensions:
  165. (lambda ()
  166. (dylan-call dylan:error
  167. "make -- array needs dimensions"
  168. class rest))))
  169. (fill-value (dylan::find-keyword rest 'fill: (lambda () #F))))
  170. (if (not (subclass? (get-type dimensions) <sequence>))
  171. (dylan-call dylan:error
  172. "make -- array dimensions not a sequence"
  173. class dimensions))
  174. (let ((instance (dylan::make-<object> <array>))
  175. (dim-list
  176. (iterate->list
  177. (lambda (elem)
  178. (if (not (and (integer? elem)
  179. (positive? elem)))
  180. (dylan-call
  181. dylan:error
  182. "make -- dimension elements not all positive integers"
  183. class dimensions elem)
  184. elem))
  185. dimensions)))
  186. (dylan-call dylan:set-array-value!
  187. instance
  188. (make-multi-dimensional-array dim-list fill-value))
  189. (dylan-call dylan:set-array-dimensions! instance dim-list)
  190. instance)))))
  191. ;;;;
  192. ;;;; Operations on Arrays (page 113 )
  193. ;;;;
  194. (define dylan:aref
  195. (dylan::generic-fn 'aref
  196. (make-param-list `((ARRAY ,<array>)) #F #T #F)
  197. (lambda (array-instance . init-indices)
  198. (if (null? init-indices)
  199. (dylan-call dylan:error
  200. "aref -- no indices given" array-instance))
  201. (let loop ((array (dylan-call dylan:get-array-value array-instance))
  202. (indices init-indices))
  203. (if (vector? array)
  204. (let ((size (vector-length array))
  205. (index (car indices)))
  206. (if (>= index size)
  207. (dylan-call dylan:error
  208. "aref -- subscript out of range"
  209. array-instance init-indices array index))
  210. (if (null? (cdr indices))
  211. (vector-ref array index)
  212. (loop (vector-ref array index) (cdr indices))))
  213. (dylan-call dylan:error
  214. "aref -- too many subscripts"
  215. array-instance init-indices indices))))))
  216. (define dylan:setter/aref/
  217. (dylan::generic-fn 'aref
  218. (make-param-list `((ARRAY ,<array>)) #F #T #F)
  219. (lambda (array-instance . indices-and-new-value)
  220. (if (null? indices-and-new-value)
  221. (dylan-call dylan:error
  222. "(setter aref) -- no indices and new-value given"
  223. array-instance))
  224. (let ((new-value (list-ref indices-and-new-value
  225. (- (length indices-and-new-value) 1)))
  226. (indices (but-last indices-and-new-value)))
  227. (if (not (pair? indices))
  228. (dylan-call dylan:error
  229. "(setter aref) -- no indices given"
  230. array-instance indices-and-new-value))
  231. (let loop ((array (dylan-call dylan:get-array-value array-instance))
  232. (indices indices))
  233. (if (vector? array)
  234. (let ((size (vector-length array))
  235. (index (car indices)))
  236. (if (>= index size)
  237. (dylan-call dylan:error
  238. "(setter aref) -- subscript out of range"
  239. array-instance indices-and-new-value
  240. array index))
  241. (if (null? (cdr indices))
  242. (if (vector? (vector-ref array index))
  243. (dylan-call
  244. dylan:error
  245. "(setter aref) -- indices need to point to an element"
  246. array-instance indices-and-new-value array index)
  247. (begin
  248. (vector-set! array index new-value)
  249. new-value))
  250. (loop (vector-ref array index) (cdr indices))))
  251. (dylan-call dylan:error
  252. "(setter aref) -- too many subscripts"
  253. array-instance indices-and-new-value indices)))))))
  254. (define dylan:dimensions
  255. (dylan::generic-fn 'dimensions
  256. (make-param-list `((ARRAY ,<array>)) #F #F #F)
  257. (lambda (array)
  258. (dylan-call dylan:get-array-dimensions array))))
  259. (add-method
  260. dylan:element
  261. (dylan::dylan-callable->method
  262. (make-param-list `((ARRAY ,<array>) (INDEX ,<sequence>)) #F #F '(default:))
  263. (lambda (multiple-values next-method array-instance init-indices . rest)
  264. multiple-values
  265. (dylan::keyword-validate next-method rest '(default:))
  266. (let* ((default (dylan::find-keyword rest 'default: (lambda () #F)))
  267. (error-report (lambda args (if default
  268. default
  269. (apply dylan:error args)))))
  270. (if (dylan-call dylan:empty? init-indices)
  271. (error-report "element -- no indices given" array-instance)
  272. (let loop ((array
  273. (dylan-call dylan:get-array-value array-instance))
  274. (index-state
  275. (dylan-call dylan:initial-state init-indices)))
  276. (let ((index (dylan-call dylan:current-element
  277. init-indices index-state)))
  278. (if (vector? array)
  279. (cond ((>= index (vector-length array))
  280. (error-report "element -- subscript out of range"
  281. array-instance init-indices array index))
  282. ((not
  283. (dylan-call dylan:next-state
  284. init-indices index-state))
  285. (vector-ref array index))
  286. (else (loop (vector-ref array index)
  287. (dylan-call dylan:next-state
  288. init-indices index-state))))
  289. (error-report "element -- too many subscripts"
  290. array-instance init-indices index)))))))))
  291. (add-method dylan:current-key
  292. (dylan::function->method
  293. (make-param-list `((ARRAY ,<array>) (STATE ,<object>)) #F #F #F)
  294. (lambda (array state)
  295. array ; Ignored
  296. state)))
  297. ;;;
  298. ;;; Mutable Collections
  299. ;;;
  300. (add-method dylan:setter/current-element/
  301. (dylan::function->method
  302. (make-param-list
  303. `((ARRAY ,<array>) (STATE ,<object>) (new-value ,<object>)) #F #F #F)
  304. (lambda (array state new-value)
  305. array ; Ignored
  306. (let loop ((vectors (dylan-call dylan:get-array-value array))
  307. (state (vector->list state)))
  308. (if (= (length state) 1)
  309. (begin
  310. (vector-set! vectors (car state) new-value)
  311. new-value)
  312. (loop (vector-ref vectors (car state))
  313. (cdr state)))))))