PageRenderTime 28ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/kits/gambit/src/runtime-collections-string.scm

http://github.com/pablomarx/Thomas
Racket | 351 lines | 247 code | 38 blank | 66 comment | 25 complexity | 88b9f2810346c601a788a90a41f54cd9 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-string.scm,v 1.17 1992/08/31 05:26:50 birkholz Exp $
  38. ;;;; Specializations for string and byte-string types.
  39. (add-method dylan:as
  40. (dylan::function->method
  41. (make-param-list `((CLASS ,(dylan::make-singleton <byte-string>))
  42. (COLLECTION ,<collection>)) #F #F #F)
  43. (lambda (class collection)
  44. class
  45. (if (dylan-call dylan:instance? collection <byte-string>)
  46. collection
  47. (let* ((size (dylan-call dylan:size collection))
  48. (new-string (make-string size)))
  49. (do ((state (dylan-call dylan:initial-state collection)
  50. (dylan-call dylan:next-state collection state))
  51. (index 0 (+ index 1)))
  52. ((not state) new-string)
  53. (let ((cur-element
  54. (dylan-call dylan:current-element collection state)))
  55. (string-set! new-string index
  56. (dylan-call
  57. dylan:as <character> cur-element)))))))))
  58. (add-method dylan:as
  59. (dylan::function->method
  60. (make-param-list `((CLASS ,(dylan::make-singleton <string>))
  61. (COLLECTION ,<collection>)) #F #F #F)
  62. (lambda (class collection)
  63. class
  64. (if (dylan-call dylan:instance? collection <string>)
  65. collection
  66. (dylan-call dylan:as <byte-string> collection)))))
  67. ;;;
  68. ;;; BYTE-STRING MAKE yields a Scheme string
  69. ;;;
  70. ;;; size keyword overrides inherited dimensions keyword (which is not used)
  71. ;;;
  72. (add-method
  73. dylan:make
  74. (dylan::dylan-callable->method
  75. (make-param-list `((STRING ,(dylan::make-singleton <byte-string>)))
  76. #F #F '(size: fill:))
  77. (lambda (multiple-values next-method class . rest)
  78. multiple-values class ; Not used
  79. (dylan::keyword-validate next-method rest '(size: fill:))
  80. (let* ((size (dylan::find-keyword rest 'size: (lambda () 0)))
  81. (have-fill? #T)
  82. (fill (dylan::find-keyword rest 'fill:
  83. (lambda () (set! have-fill? #F) #F))))
  84. (if (or (not (integer? size)) (negative? size))
  85. (dylan-call dylan:error
  86. "(make (singleton <string>)) -- size: invalid" size))
  87. (if (and have-fill? (not (char? fill)))
  88. (dylan-call dylan:error
  89. "(make (singleton <string>)) -- fill: not a character"
  90. fill))
  91. (if have-fill?
  92. (make-string size fill)
  93. (make-string size))))))
  94. ;;;
  95. ;;; STRING SPECIALIZED MAKE
  96. ;;; And we'll make <string> turn into <byte-string>
  97. ;;;
  98. (add-method dylan:make
  99. (dylan::function->method
  100. (make-param-list `((STRING ,(dylan::make-singleton <string>)))
  101. #F #F #T)
  102. (lambda (class . rest)
  103. class ; Ignored
  104. (dylan-apply dylan:make <byte-string> rest))))
  105. ;;;
  106. ;;; UNICODE-STRING SPECIALIZED MAKE
  107. ;;; <unicode-string> not supported
  108. ;;;
  109. (add-method dylan:make
  110. (dylan::function->method
  111. (make-param-list `((UNICODE
  112. ,(dylan::make-singleton <unicode-string>)))
  113. #F #F #T)
  114. (lambda (class . rest)
  115. class ; Ignored
  116. rest ; Ignored
  117. (dylan-call dylan:error
  118. "(make (singleton <unicode-string>)) -- not supported"))))
  119. ;;;
  120. ;;; FUNCTIONS FOR COLLECTIONS (page 99)
  121. ;;;
  122. (add-method dylan:size
  123. (one-arg 'STRING <byte-string>
  124. (lambda (string) (string-length string))))
  125. (add-method dylan:class-for-copy
  126. (dylan::function->method one-string (lambda (x) x <byte-string>)))
  127. ;;;;
  128. ;;;; Functions for Sequences (page 104)
  129. ;;;;
  130. (add-method dylan:add
  131. (dylan::function->method one-byte-string-and-an-object
  132. (lambda (the-string new-element)
  133. (if (char? new-element)
  134. (string-append (string new-element) the-string)
  135. (dylan-call dylan:error "(add <byte-string> <object>) -- cannot add a non-character to string" the-string new-element)))))
  136. (add-method dylan:concatenate
  137. (dylan::function->method
  138. (make-param-list `((BYTE-STRING ,<byte-string>)) #F 'REST #F)
  139. (lambda (string-1 . rest)
  140. (let loop ((result string-1)
  141. (rest-strings
  142. (map (lambda (seq)
  143. (dylan-call dylan:as <byte-string> seq))
  144. rest)))
  145. (if (null? rest-strings)
  146. result
  147. (loop (string-append result (car rest-strings))
  148. (cdr rest-strings)))))))
  149. (add-method dylan:concatenate
  150. (dylan::function->method
  151. (make-param-list `((STRING ,<string>)) #F 'REST #F)
  152. (lambda (string-1 . rest)
  153. (dylan-call dylan:apply dylan:concatenate string-1 rest))))
  154. (add-method dylan:reverse
  155. (dylan::function->method one-byte-string
  156. (lambda (string-1)
  157. (let ((result (make-string (string-length string-1))))
  158. (do ((from (- (string-length string-1) 1) (- from 1))
  159. (to 0 (+ to 1)))
  160. ((< from 0) result)
  161. (string-set! result to (string-ref string-1 from))
  162. result)))))
  163. (add-method dylan:reverse!
  164. (dylan::function->method one-byte-string
  165. (lambda (string-1)
  166. (do ((from (- (string-length string-1) 1) (- from 1))
  167. (to 0 (+ to 1)))
  168. ((<= from to) string-1)
  169. (let ((to-char (string-ref string-1 to)))
  170. (string-set! string-1 to (string-ref string-1 from))
  171. (string-set! string-1 from to-char))))))
  172. (add-method dylan:first
  173. (dylan::function->method one-string
  174. (lambda (string)
  175. (if (= (string-length string) 0)
  176. (dylan-call dylan:error "(first <string>) -- string is empty" string)
  177. (string-ref string 0)))))
  178. (add-method dylan:first
  179. (dylan::function->method one-byte-string
  180. (lambda (string)
  181. (if (= (string-length string) 0)
  182. (dylan-call dylan:error
  183. "(first <byte-string>) -- byte-string is empty" string)
  184. (string-ref string 0)))))
  185. (add-method dylan:second
  186. (dylan::function->method one-string
  187. (lambda (string)
  188. (if (< (string-length string) 2)
  189. (dylan-call dylan:error
  190. "(second <string>) -- string doesn't have 2 elements"
  191. string)
  192. (string-ref string 1)))))
  193. (add-method dylan:second
  194. (dylan::function->method one-byte-string
  195. (lambda (string)
  196. (if (< (string-length string) 2)
  197. (dylan-call dylan:error
  198. "(second <string>) -- string doesn't have 2 elements"
  199. string)
  200. (string-ref string 1)))))
  201. (add-method dylan:third
  202. (dylan::function->method one-string
  203. (lambda (string)
  204. (if (< (string-length string) 3 )
  205. (dylan-call dylan:error
  206. "(third <string>) -- string doesn't have 3 elements"
  207. string)
  208. (string-ref string 2)))))
  209. (add-method dylan:third
  210. (dylan::function->method one-byte-string
  211. (lambda (string)
  212. (if (< (string-length string) 3 )
  213. (dylan-call dylan:error
  214. "(third <byte-string>) -- string doesn't have 3 elements"
  215. string)
  216. (string-ref string 2)))))
  217. (add-method dylan:last
  218. (dylan::function->method one-string
  219. (lambda (string)
  220. (let ((sl (string-length string)))
  221. (if (zero? sl)
  222. (dylan-call dylan:error "(last <string>) -- string is empty" string)
  223. (string-ref string (- sl 1)))))))
  224. (add-method dylan:last
  225. (dylan::function->method one-byte-string
  226. (lambda (string)
  227. (let ((sl (string-length string)))
  228. (if (zero? sl)
  229. (dylan-call dylan:error
  230. "(last <byte-string>) -- byte-string is empty" string)
  231. (string-ref string (- sl 1)))))))
  232. ;;;; Operations on Strings (page 119)
  233. (add-method dylan:binary< (dylan::function->method two-strings string<?))
  234. ;; Generic function dylan:as-lowercase defined in runtime-functions.scm.
  235. (add-method
  236. dylan:as-lowercase
  237. (dylan::function->method
  238. (make-param-list `((BYTE-STRING ,<byte-string>)) #F #F #F)
  239. (lambda (string)
  240. (list->string (map (lambda (char) (char-downcase char))
  241. (string->list string))))))
  242. (define dylan:as-lowercase!
  243. (dylan::generic-fn 'as-lowercase! one-string #F))
  244. (add-method
  245. dylan:as-lowercase!
  246. (dylan::function->method
  247. (make-param-list `((BYTE-STRING ,<byte-string>)) #F #F #F)
  248. (lambda (string)
  249. (do ((index 0 (+ index 1)))
  250. ((>= index (string-length string)) string)
  251. (string-set! string index (char-downcase (string-ref string index)))))))
  252. ;; Generic function dylan:as-uppercase defined in runtime-functions.scm.
  253. (add-method
  254. dylan:as-uppercase
  255. (dylan::function->method
  256. (make-param-list `((BYTE-STRING ,<byte-string>)) #F #F #F)
  257. (lambda (string)
  258. (list->string (map (lambda (char) (char-upcase char))
  259. (string->list string))))))
  260. (define dylan:as-uppercase!
  261. (dylan::generic-fn 'as-uppercase! one-string #F))
  262. (add-method
  263. dylan:as-uppercase!
  264. (dylan::function->method
  265. (make-param-list `((BYTE-STRING ,<byte-string>)) #F #F #F)
  266. (lambda (string)
  267. (do ((index 0 (+ index 1)))
  268. ((>= index (string-length string)) string)
  269. (string-set! string index (char-upcase (string-ref string index)))))))
  270. (add-method dylan:previous-state ; Not specified in the manual
  271. (dylan::function->method
  272. (make-param-list `((STRING ,<string>) (STATE ,<number>)) #F #F #F)
  273. (lambda (string offset)
  274. string ; unused
  275. (if (= offset 0) #F (- offset 1)))))
  276. ;;;
  277. ;;; Collection Keys
  278. ;;;
  279. (add-method
  280. dylan:element
  281. (dylan::dylan-callable->method
  282. (make-param-list `((BYTE-STRING ,<byte-string>) (INDEX ,<integer>))
  283. #F #F '(default:))
  284. (lambda (multiple-values next-method string-value index . rest)
  285. multiple-values
  286. (dylan::keyword-validate next-method rest '(default:))
  287. (let ((size (string-length string-value)))
  288. (if (and (>= index 0) (< index size))
  289. (string-ref string-value index)
  290. (dylan::find-keyword
  291. rest '(default:)
  292. (lambda ()
  293. (dylan-call dylan:error "(element <byte-string> <integer>) -- invalid index with no default value" string-value index))))))))
  294. ;;;
  295. ;;; Mutable Collections
  296. ;;;
  297. (add-method dylan:setter/current-element/
  298. (dylan::function->method
  299. (make-param-list
  300. `((BYTE-STRING ,<byte-string>) (STATE ,<object>) (new-value ,<object>))
  301. #F #F #F)
  302. (lambda (the-string state new-value)
  303. (string-set! the-string (vector-ref state 0) new-value)
  304. new-value)))
  305. (add-method dylan:setter/element/
  306. (dylan::function->method
  307. (make-param-list
  308. `((BYTE-STRING ,<byte-string>) (INDEX ,<object>) (NEW-VALUE ,<object>))
  309. #F #F #F)
  310. (lambda (string index new-value)
  311. (string-set! string index new-value)
  312. new-value)))