base.scm 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. ;;; R7RS compatibility libraries
  2. ;;; Copyright (C) 2019-2021, 2023 Free Software Foundation, Inc.
  3. ;;;
  4. ;;; This library is free software: you can redistribute it and/or modify
  5. ;;; it under the terms of the GNU Lesser General Public License as
  6. ;;; published by the Free Software Foundation, either version 3 of the
  7. ;;; License, or (at your option) any later version.
  8. ;;;
  9. ;;; This library is distributed in the hope that it will be useful, but
  10. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;; Lesser General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU Lesser General Public
  15. ;;; License along with this program. If not, see
  16. ;;; <http://www.gnu.org/licenses/>.
  17. ;;; Based on code from https://gitlab.com/akku/akku-scm, written
  18. ;;; 2018-2019 by Göran Weinholt <goran@weinholt.se>, as well as
  19. ;;; https://github.com/okuoku/yuni, written 2014-2018 by OKUMURA Yuki
  20. ;;; <mjt@cltn.org>. This code was originally released under the
  21. ;;; following terms:
  22. ;;;
  23. ;;; To the extent possible under law, the author(s) have dedicated
  24. ;;; all copyright and related and neighboring rights to this
  25. ;;; software to the public domain worldwide. This software is
  26. ;;; distributed without any warranty.
  27. ;;;
  28. ;;; See <http://creativecommons.org/publicdomain/zero/1.0/>, for a
  29. ;;; copy of the CC0 Public Domain Dedication.
  30. (define-module (scheme base)
  31. #:use-module (srfi srfi-9)
  32. #:use-module (srfi srfi-11)
  33. #:use-module (ice-9 exceptions)
  34. #:use-module ((srfi srfi-34) #:select (guard))
  35. #:use-module (ice-9 ports)
  36. #:use-module (ice-9 textual-ports)
  37. #:use-module (ice-9 binary-ports)
  38. #:use-module (rnrs bytevectors)
  39. #:export (error-object-message error-object-irritants
  40. file-error?
  41. (r7:error . error)
  42. (r7:cond-expand . cond-expand)
  43. (r7:include . include)
  44. (r7:include-ci . include-ci)
  45. (r7:let-syntax . let-syntax)
  46. member assoc list-copy map for-each
  47. binary-port? textual-port?
  48. open-input-bytevector
  49. open-output-bytevector get-output-bytevector
  50. peek-u8 read-u8 read-bytevector read-bytevector!
  51. read-string read-line
  52. (r7:string-for-each . string-for-each)
  53. write-u8 write-bytevector write-string flush-output-port
  54. (r7:string-map . string-map)
  55. bytevector bytevector-append
  56. string->vector vector->string
  57. (r7:string->utf8 . string->utf8)
  58. (r7:vector->list . vector->list)
  59. vector-append vector-for-each vector-map
  60. (r7:bytevector-copy . bytevector-copy)
  61. (r7:bytevector-copy! . bytevector-copy!)
  62. (r7:utf8->string . utf8->string)
  63. square
  64. (r7:expt . expt)
  65. boolean=? symbol=?
  66. features
  67. input-port-open? output-port-open?)
  68. #:re-export
  69. (_
  70. ... => else
  71. * + - / < <= = > >= abs and append apply assq assv begin
  72. boolean?
  73. bytevector-length
  74. bytevector-u8-ref bytevector-u8-set! bytevector? caar cadr
  75. call-with-current-continuation call-with-port call-with-values
  76. call/cc car case cdar cddr cdr ceiling char->integer char-ready?
  77. char<=? char<? char=? char>=? char>? char? close-input-port
  78. close-output-port close-port complex? cond cons
  79. current-error-port current-input-port current-output-port define
  80. define-record-type define-syntax define-values denominator do
  81. dynamic-wind eof-object eof-object? eq? equal? eqv?
  82. (exception? . error-object?)
  83. even?
  84. (inexact->exact . exact)
  85. (exact->inexact . inexact)
  86. exact-integer-sqrt exact-integer? exact?
  87. floor floor-quotient floor-remainder floor/
  88. gcd
  89. get-output-string guard if inexact?
  90. input-port? integer->char integer? lambda lcm
  91. length let let* let*-values let-values letrec letrec*
  92. letrec-syntax list list->string list->vector list-ref
  93. list-set! list-tail list? make-bytevector make-list make-parameter
  94. make-string make-vector max memq memv min modulo
  95. negative? newline not null? number->string number? numerator odd?
  96. open-input-string
  97. open-output-string or output-port? pair?
  98. parameterize peek-char port? positive? procedure?
  99. quasiquote quote quotient
  100. (raise-exception . raise)
  101. raise-continuable
  102. rational?
  103. rationalize read-char
  104. (lexical-error? . read-error?)
  105. real? remainder reverse round set!
  106. set-car! set-cdr! string string->list string->number
  107. string->symbol string-append
  108. string-copy string-copy! string-fill!
  109. string-length string-ref string-set! string<=? string<?
  110. string=? string>=? string>? string? substring symbol->string
  111. symbol? syntax-error syntax-rules truncate
  112. truncate-quotient truncate-remainder truncate/
  113. (char-ready? . u8-ready?)
  114. unless
  115. unquote unquote-splicing values
  116. vector vector-copy vector-copy! vector-fill!
  117. vector-length vector-ref vector-set! vector?
  118. when with-exception-handler write-char
  119. zero?))
  120. (define* (member x ls #:optional (= equal?))
  121. (cond
  122. ((eq? = eq?) (memq x ls))
  123. ((eq? = eqv?) (memv x ls))
  124. (else
  125. (unless (procedure? =)
  126. (error "not a procedure" =))
  127. (let lp ((ls ls))
  128. (cond
  129. ((null? ls) #f)
  130. ((= (car ls) x) ls)
  131. (else (lp (cdr ls))))))))
  132. (define* (assoc x ls #:optional (= equal?))
  133. (cond
  134. ((eq? = eq?) (assq x ls))
  135. ((eq? = eqv?) (assv x ls))
  136. (else
  137. (unless (procedure? =)
  138. (error "not a procedure" =))
  139. (let lp ((ls ls))
  140. (cond
  141. ((null? ls) #f)
  142. ((= (caar ls) x) (car ls))
  143. (else (lp (cdr ls))))))))
  144. (define (list-copy x)
  145. (if (pair? x)
  146. (cons (car x) (list-copy (cdr x)))
  147. x))
  148. (define (circular-list? x)
  149. (and (pair? x)
  150. (let lp ((hare (cdr x)) (tortoise x))
  151. (and (pair? hare)
  152. (let ((hare (cdr hare)))
  153. (and (pair? hare)
  154. (or (eq? hare tortoise)
  155. (lp (cdr hare) (cdr tortoise)))))))))
  156. (define map
  157. (case-lambda
  158. ((f l)
  159. (unless (or (list? l)
  160. (circular-list? l))
  161. (scm-error 'wrong-type-arg "map" "Not a list: ~S"
  162. (list l) #f))
  163. (let map1 ((l l))
  164. (if (pair? l)
  165. (cons (f (car l)) (map1 (cdr l)))
  166. '())))
  167. ((f l1 l2)
  168. (cond
  169. ((list? l1)
  170. (unless (or (list? l2) (circular-list? l2))
  171. (scm-error 'wrong-type-arg "map" "Not a list: ~S"
  172. (list l2) #f)))
  173. ((circular-list? l1)
  174. (unless (list? l2)
  175. (scm-error 'wrong-type-arg "map" "Not a finite list: ~S"
  176. (list l2) #f)))
  177. (else
  178. (scm-error 'wrong-type-arg "map" "Not a list: ~S"
  179. (list l1) #f)))
  180. (let map2 ((l1 l1) (l2 l2))
  181. (if (and (pair? l1) (pair? l2))
  182. (cons (f (car l1) (car l2))
  183. (map2 (cdr l1) (cdr l2)))
  184. '())))
  185. ((f l1 . rest)
  186. (let ((lists (cons l1 rest)))
  187. (unless (and-map list? lists)
  188. (unless (or-map list? lists)
  189. (scm-error 'wrong-type-arg "map"
  190. "Arguments do not contain a finite list" '() #f))
  191. (for-each (lambda (x)
  192. (unless (or (list? x) (circular-list? x))
  193. (scm-error 'wrong-type-arg "map" "Not a list: ~S"
  194. (list x) #f)))
  195. lists))
  196. (let mapn ((lists lists))
  197. (if (and-map pair? lists)
  198. (cons (apply f (map car lists)) (mapn (map cdr lists)))
  199. '()))))))
  200. (define for-each
  201. (case-lambda
  202. ((f l)
  203. (unless (or (list? l)
  204. (circular-list? l))
  205. (scm-error 'wrong-type-arg "for-each" "Not a list: ~S"
  206. (list l) #f))
  207. (let for-each1 ((l l))
  208. (when (pair? l)
  209. (f (car l))
  210. (for-each1 (cdr l)))))
  211. ((f l1 l2)
  212. (cond
  213. ((list? l1)
  214. (unless (or (list? l2) (circular-list? l2))
  215. (scm-error 'wrong-type-arg "for-each" "Not a list: ~S"
  216. (list l2) #f)))
  217. ((circular-list? l1)
  218. (unless (list? l2)
  219. (scm-error 'wrong-type-arg "for-each" "Not a finite list: ~S"
  220. (list l2) #f)))
  221. (else
  222. (scm-error 'wrong-type-arg "for-each" "Not a list: ~S"
  223. (list l1) #f)))
  224. (let for-each2 ((l1 l1) (l2 l2))
  225. (when (and (pair? l1) (pair? l2))
  226. (f (car l1) (car l2))
  227. (for-each2 (cdr l1) (cdr l2)))))
  228. ((f l1 . rest)
  229. (let ((lists (cons l1 rest)))
  230. (unless (and-map list? lists)
  231. (unless (or-map list? lists)
  232. (scm-error 'wrong-type-arg "for-each"
  233. "Arguments do not contain a finite list" '() #f))
  234. (for-each (lambda (x)
  235. (unless (or (list? x) (circular-list? x))
  236. (scm-error 'wrong-type-arg "for-each" "Not a list: ~S"
  237. (list x) #f)))
  238. lists))
  239. (let for-eachn ((lists lists))
  240. (when (and-map pair? lists)
  241. (apply f (map car lists))
  242. (for-eachn (map cdr lists))))))))
  243. ;; FIXME.
  244. (define (file-error? x) #f)
  245. (define (error-object-message obj)
  246. (and (exception-with-message? obj)
  247. (exception-message obj)))
  248. (define (error-object-irritants obj)
  249. (and (exception-with-irritants? obj)
  250. (exception-irritants obj)))
  251. (define (r7:error message . irritants)
  252. (raise-exception
  253. (let ((exn (make-exception-with-message message)))
  254. (if (null? irritants)
  255. exn
  256. (make-exception exn
  257. (make-exception-with-irritants irritants))))))
  258. (include-from-path "scheme/features.scm")
  259. (define-syntax r7:cond-expand
  260. (lambda (x)
  261. (define (has-req? req)
  262. (syntax-case req (and or not library)
  263. ((and req ...)
  264. (and-map has-req? #'(req ...)))
  265. ((or req ...)
  266. (or-map has-req? #'(req ...)))
  267. ((not req)
  268. (not (has-req? #'req)))
  269. ((library lib-name)
  270. (->bool
  271. (false-if-exception
  272. (resolve-r6rs-interface
  273. (syntax->datum #'lib-name)))))
  274. (id
  275. (identifier? #'id)
  276. (memq (syntax->datum #'id) (features)))))
  277. (syntax-case x (else)
  278. ((_)
  279. (syntax-violation 'cond-expand "Unfulfilled cond-expand" x))
  280. ((_ (else body ...))
  281. #'(begin body ...))
  282. ((_ (req body ...) more-clauses ...)
  283. (if (has-req? #'req)
  284. #'(begin body ...)
  285. #'(r7:cond-expand more-clauses ...))))))
  286. (define-syntax-rule (r7:include fn* ...)
  287. (begin (include fn*) ...))
  288. (define-syntax-rule (r7:include-ci fn* ...)
  289. (begin (include-ci fn*) ...))
  290. (define-syntax-rule (r7:let-syntax ((vars trans) ...) . expr)
  291. (let-syntax ((vars trans) ...)
  292. (let () . expr)))
  293. (define (boolean=? x y . y*)
  294. (unless (boolean? x) (error "not a boolean" x))
  295. (unless (boolean? y) (error "not a boolean" y))
  296. (and (eq? x y)
  297. (or (null? y*)
  298. (apply boolean=? x y*))))
  299. (define (symbol=? x y . y*)
  300. (unless (symbol? x) (error "not a symbol" x))
  301. (unless (symbol? y) (error "not a symbol" y))
  302. (and (symbol? x)
  303. (eq? x y)
  304. (or (null? y*)
  305. (apply symbol=? x y*))))
  306. (define (binary-port? p) (port? p))
  307. (define (textual-port? p) (port? p))
  308. (define (open-input-bytevector bv) (open-bytevector-input-port bv))
  309. (define (open-output-bytevector)
  310. (let-values (((p extract) (open-bytevector-output-port)))
  311. (define pos 0)
  312. (define buf #vu8())
  313. (define (read! target target-start count)
  314. (when (zero? (- (bytevector-length buf) pos))
  315. (set! buf (bytevector-append buf (extract)))) ;resets p
  316. (let ((count (min count (- (bytevector-length buf) pos))))
  317. (bytevector-copy! buf pos
  318. target target-start count)
  319. (set! pos (+ pos count))
  320. count))
  321. (define (write! bv start count)
  322. (put-bytevector p bv start count)
  323. (set! pos (+ pos count))
  324. count)
  325. (define (get-position)
  326. pos)
  327. (define (set-position! new-pos)
  328. (set! pos new-pos))
  329. (define (close)
  330. (close-port p))
  331. ;; It's actually an input/output port, but only
  332. ;; get-output-bytevector should ever read from it. If it was just
  333. ;; an output port then there would be no good way for
  334. ;; get-output-bytevector to read the data. -weinholt
  335. (make-custom-binary-input/output-port
  336. "bytevector" read! write! get-position set-position! close)))
  337. (define (get-output-bytevector port)
  338. ;; R7RS says "It is an error if port was not created with
  339. ;; open-output-bytevector.", so we can safely assume that the port
  340. ;; was created by open-output-bytevector. -weinholt
  341. (seek port 0 SEEK_SET)
  342. (let ((bv (get-bytevector-all port)))
  343. (if (eof-object? bv)
  344. #vu8()
  345. bv)))
  346. (define* (peek-u8 #:optional (port (current-input-port)))
  347. (lookahead-u8 port))
  348. (define* (read-u8 #:optional (port (current-input-port)))
  349. (get-u8 port))
  350. (define* (read-bytevector len #:optional (port (current-input-port)))
  351. (get-bytevector-n port len))
  352. (define* (read-string len #:optional (port (current-input-port)))
  353. (get-string-n port len))
  354. (define* (read-bytevector! bv #:optional (port (current-input-port))
  355. (start 0) (end (bytevector-length bv)))
  356. (get-bytevector-n! port bv start (- end start)))
  357. (define* (read-line #:optional (port (current-input-port)))
  358. (get-line port))
  359. (define* (write-u8 obj #:optional (port (current-output-port)))
  360. (put-u8 port obj))
  361. (define* (write-bytevector bv #:optional (port (current-output-port))
  362. (start 0) (end (bytevector-length bv)))
  363. (put-bytevector port bv start (- end start)))
  364. (define* (write-string str #:optional (port (current-output-port))
  365. (start 0) (end (string-length str)))
  366. (put-string port str start (- end start)))
  367. (define* (flush-output-port #:optional (port (current-output-port)))
  368. (force-output port))
  369. (define (r7:string-map proc s . s*)
  370. (if (null? s*)
  371. (string-map proc s)
  372. (list->string (apply map proc (string->list s) (map string->list
  373. s*)))))
  374. (define r7:string-for-each
  375. (case-lambda
  376. "Like @code{for-each}, but takes strings instead of lists."
  377. ((proc s) (string-for-each proc s))
  378. ((proc s1 s2)
  379. (let ((len (min (string-length s1)
  380. (string-length s2))))
  381. (let loop ((i 0))
  382. (when (< i len)
  383. (proc (string-ref s1 i)
  384. (string-ref s2 i))
  385. (loop (+ i 1))))))
  386. ((proc . strings)
  387. (let ((len (apply min (map string-length strings))))
  388. (let loop ((i 0))
  389. (when (< i len)
  390. (apply proc (map (lambda (s)
  391. (string-ref s i))
  392. strings))
  393. (loop (+ i 1))))))))
  394. (define (bytevector . lis)
  395. (u8-list->bytevector lis))
  396. (define (call-with-bytevector-output-port proc)
  397. (call-with-values (lambda () (open-bytevector-output-port))
  398. (lambda (port get)
  399. (proc port)
  400. (get))))
  401. (define (bytevector-append . bvs)
  402. (call-with-bytevector-output-port
  403. (lambda (p)
  404. (for-each (lambda (bv) (put-bytevector p bv)) bvs))))
  405. (define string->vector
  406. (case-lambda
  407. ((str) (list->vector (string->list str)))
  408. ((str start) (string->vector (substring str start)))
  409. ((str start end) (string->vector (substring str start end)))))
  410. (define r7:string->utf8
  411. (case-lambda
  412. ((str) (string->utf8 str))
  413. ((str start) (string->utf8 (substring str start)))
  414. ((str start end) (string->utf8 (substring str start end)))))
  415. ;;; vector
  416. (define r7:vector->list
  417. (case-lambda*
  418. ((v) (vector->list v))
  419. ((v start #:optional (end (vector-length v)))
  420. (vector->list (vector-copy v start end)))))
  421. (define vector-map
  422. (case-lambda*
  423. ((f v)
  424. (let* ((len (vector-length v))
  425. (out (make-vector len #f)))
  426. (let lp ((i 0))
  427. (when (< i len)
  428. (vector-set! out i (f (vector-ref v i)))
  429. (lp (1+ i))))
  430. out))
  431. ((f v . v*)
  432. (list->vector (apply map f (map vector->list (cons v v*)))))))
  433. (define vector-for-each
  434. (case-lambda*
  435. ((f v)
  436. (let lp ((i 0))
  437. (when (< i (vector-length v))
  438. (f (vector-ref v i))
  439. (lp (1+ i)))))
  440. ((f v . v*)
  441. (let ((len (apply min (vector-length v) (map vector-length v*))))
  442. (let lp ((i 0))
  443. (when (< i len)
  444. (apply f (vector-ref v i) (map (lambda (v) (vector-ref v i)) v*))
  445. (lp (1+ i))))))))
  446. (define (vector-append . vectors)
  447. (if (null? vectors)
  448. #()
  449. (let* ((len (let lp ((vectors vectors))
  450. (if (null? vectors)
  451. 0
  452. (+ (vector-length (car vectors)) (lp (cdr vectors))))))
  453. (out (make-vector len #f)))
  454. (let lp ((i 0) (j 0) (v (car vectors)) (v* (cdr vectors)))
  455. (cond
  456. ((< j (vector-length v))
  457. (vector-set! out i (vector-ref v j))
  458. (lp (1+ i) (1+ j) v v*))
  459. ((null? v*)
  460. out)
  461. (else
  462. (lp i 0 (car v*) (cdr v*))))))))
  463. (define vector->string
  464. (case-lambda*
  465. ((v) (list->string (vector->list v)))
  466. ((v start #:optional (end (vector-length v)))
  467. (vector->string (vector-copy v start end)))))
  468. (define (%subbytevector bv start end)
  469. (define mlen (- end start))
  470. (define out (make-bytevector mlen))
  471. (bytevector-copy! bv start out 0 mlen)
  472. out)
  473. (define (%subbytevector1 bv start)
  474. (%subbytevector bv start (bytevector-length bv)))
  475. (define r7:bytevector-copy!
  476. (case-lambda*
  477. ((to at from #:optional
  478. (start 0)
  479. (end (+ start
  480. (min (- (bytevector-length from) start)
  481. (- (bytevector-length to) at)))))
  482. (bytevector-copy! from start to at (- end start)))))
  483. (define r7:bytevector-copy
  484. (case-lambda*
  485. ((bv) (bytevector-copy bv))
  486. ((bv start #:optional (end (bytevector-length bv)))
  487. (%subbytevector bv start end))))
  488. (define r7:utf8->string
  489. (case-lambda*
  490. ((bv) (utf8->string bv))
  491. ((bv start #:optional (end (bytevector-length bv)))
  492. (utf8->string (%subbytevector bv start end)))))
  493. (define (square x) (* x x))
  494. (define (r7:expt x y)
  495. (if (eqv? x 0.0)
  496. (exact->inexact (expt x y))
  497. (expt x y)))
  498. (define (input-port-open? port)
  499. (and (not (port-closed? port)) (input-port? port)))
  500. (define (output-port-open? port)
  501. (and (not (port-closed? port)) (output-port? port)))