~ chicken-core (master) /r7lib.scm
Trap1;;;; r7lib.scm - R7RS library code
2;
3; Copyright (c) 2022, The CHICKEN Team
4; All rights reserved.
5;
6; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
7; conditions are met:
8;
9; Redistributions of source code must retain the above copyright notice, this list of conditions and the following
10; disclaimer.
11; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
12; disclaimer in the documentation and/or other materials provided with the distribution.
13; Neither the name of the author nor the names of its contributors may be used to endorse or promote
14; products derived from this software without specific prior written permission.
15;
16; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
17; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24; POSSIBILITY OF SUCH DAMAGE.
25
26(declare
27 (unit r7lib)
28 (disable-interrupts))
29
30(include "common-declarations.scm")
31
32(module scheme.write (display
33 write
34 write-shared
35 write-simple)
36 (import (rename scheme (display display-simple) (write write-simple))
37 (only chicken.base foldl when optional)
38 (only chicken.fixnum fx+ fx= fx<= fx-))
39
40 (define (interesting? o)
41 (or (pair? o)
42 (and (vector? o)
43 (fx<= 1 (##sys#size o)))))
44
45 (define (uninteresting? o)
46 (not (interesting? o)))
47
48 (define (display-char c p)
49 ((##sys#slot (##sys#slot p 2) 2) p c))
50
51 (define (display-string s p)
52 (let ((bv (##sys#slot s 0)))
53 ((##sys#slot (##sys#slot p 2) 3) p bv 0 (fx- (##sys#size bv) 1))))
54
55 ;; Build an alist mapping `interesting?` objects to boolean values
56 ;; indicating whether those objects occur shared in `o`.
57 (define (find-shared o cycles-only?)
58
59 (define seen '())
60 (define (seen? x) (assq x seen))
61 (define (seen! x) (set! seen (cons (cons x 1) seen)))
62
63 ;; Walk the form, tallying the number of times each object is
64 ;; encountered. This has the effect of filling `seen` with
65 ;; occurence counts for all objects satisfying `interesting?`.
66 (let walk! ((o o))
67 (when (interesting? o)
68 (cond ((seen? o) =>
69 (lambda (p)
70 (##sys#setslot p 1 (fx+ (cdr p) 1))))
71 ((pair? o)
72 (seen! o)
73 (walk! (car o))
74 (walk! (cdr o)))
75 ((vector? o)
76 (seen! o)
77 (let ((len (##sys#size o)))
78 (do ((i 0 (fx+ i 1)))
79 ((fx= i len))
80 (walk! (##sys#slot o i))))))
81 ;; If we're only interested in cycles and this object isn't
82 ;; self-referential, discount it (resulting in `write` rather
83 ;; than `write-shared` behavior).
84 (when cycles-only?
85 (let ((p (seen? o)))
86 (when (fx<= (cdr p) 1)
87 (##sys#setslot p 1 0))))))
88
89 ;; Mark shared objects #t, unshared objects #f.
90 (foldl (lambda (a p)
91 (if (fx<= (cdr p) 1)
92 (cons (cons (car p) #f) a)
93 (cons (cons (car p) #t) a)))
94 '()
95 seen))
96
97 (define (write-with-shared-structure writer obj cycles-only? port)
98
99 (define label 0)
100 (define (assign-label! pair)
101 (##sys#setslot pair 1 label)
102 (set! label (fx+ label 1)))
103
104 (define shared
105 (find-shared obj cycles-only?))
106
107 (define (write-interesting/shared o)
108 (cond ((pair? o)
109 (display-char #\( port)
110 (write/shared (car o))
111 (let loop ((o (cdr o)))
112 (cond ((null? o)
113 (display-char #\) port))
114 ((and (pair? o)
115 (not (cdr (assq o shared))))
116 (display-char #\space port)
117 (write/shared (car o))
118 (loop (cdr o)))
119 (else
120 (display-string " . " port)
121 (write/shared o)
122 (display-char #\) port)))))
123 ((vector? o)
124 (display-string "#(" port)
125 (write/shared (##sys#slot o 0))
126 (let ((len (##sys#size o)))
127 (do ((i 1 (fx+ i 1)))
128 ((fx= i len)
129 (display-char #\) port))
130 (display-char #\space port)
131 (write/shared (##sys#slot o i)))))))
132
133 (define (write/shared o)
134 (if (uninteresting? o)
135 (writer o port)
136 (let* ((p (assq o shared))
137 (d (cdr p)))
138 (cond ((not d)
139 (write-interesting/shared o))
140 ((number? d)
141 (display-char #\# port)
142 (writer d port)
143 (display-char #\# port))
144 (else
145 (display-char #\# port)
146 (writer label port)
147 (display-char #\= port)
148 (assign-label! p)
149 (write-interesting/shared o))))))
150
151 (write/shared obj))
152
153 (define (display o #!optional (p ##sys#standard-output))
154 (write-with-shared-structure
155 display-simple
156 o
157 #t
158 p))
159
160 (define (write o #!optional (p ##sys#standard-output))
161 (write-with-shared-structure
162 write-simple
163 o
164 #t
165 p))
166
167 (define (write-shared o #!optional (p ##sys#standard-output))
168 (write-with-shared-structure
169 write-simple
170 o
171 #f
172 p))
173
174)
175
176(module scheme.time (current-second
177 current-jiffy
178 jiffies-per-second)
179 (import (only chicken.base define-constant)
180 (chicken foreign)
181 (only chicken.time current-seconds)
182 (only scheme + define inexact->exact))
183
184 ;; As of 2012-06-30.
185 (define-constant tai-offset 35.)
186
187 (define (current-second) (+ (current-seconds) tai-offset))
188
189 (define current-jiffy (foreign-lambda integer "clock"))
190
191 (define (jiffies-per-second) (foreign-value "CLOCKS_PER_SEC" integer))
192
193)
194
195(module scheme.file (file-exists? delete-file
196 open-input-file open-binary-input-file
197 open-output-file open-binary-output-file
198 call-with-input-file call-with-output-file
199 with-input-from-file with-output-to-file)
200 (import (only scheme and define quote let apply open-input-file open-output-file call-with-input-file
201 call-with-output-file with-input-from-file with-output-to-file)
202 (rename (only (chicken file) delete-file file-exists?) (file-exists? file-exists?/base)))
203
204 (define (open-binary-input-file fname . args)
205 (let ((p (apply open-input-file fname #:binary args)))
206 (##sys#setslot p 14 'binary)
207 p))
208
209 (define (open-binary-output-file fname . args)
210 (let ((p (apply open-output-file fname #:binary args)))
211 (##sys#setslot p 14 'binary)
212 p))
213
214 (define (file-exists? fname)
215 (and (file-exists?/base fname) #t))
216
217)
218
219(module scheme.process-context (command-line
220 emergency-exit
221 exit
222 get-environment-variable
223 get-environment-variables)
224 (import scheme
225 chicken.process-context
226 chicken.type
227 (rename chicken.base (exit chicken-exit)))
228
229(define (command-line)
230 ;; Don't cache these; they may be parameterized at any time!
231 (cons (program-name) (command-line-arguments)))
232
233(define (->exit-status obj)
234 (cond ((integer? obj) obj)
235 ((eq? obj #f) 1)
236 (else 0)))
237
238(define (exit #!optional (obj 0))
239 ;; ##sys#dynamic-unwind is hidden, have to unwind manually.
240 ; (##sys#dynamic-unwind '() (length ##sys#dynamic-winds))
241 (let unwind ()
242 (unless (null? ##sys#dynamic-winds)
243 (let ((after (cdar ##sys#dynamic-winds)))
244 (set! ##sys#dynamic-winds (cdr ##sys#dynamic-winds))
245 (after)
246 (unwind))))
247 ;; The built-in exit runs cleanup handlers for us.
248 (chicken-exit (->exit-status obj)))
249
250)
251