.
[bpt/guile.git] / ice-9 / boot-9.scm
CommitLineData
0f2d19dd
JB
1;;; installed-scm-file
2
3;;;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
4;;;;
5;;;; This program is free software; you can redistribute it and/or modify
6;;;; it under the terms of the GNU General Public License as published by
7;;;; the Free Software Foundation; either version 2, or (at your option)
8;;;; any later version.
9;;;;
10;;;; This program is distributed in the hope that it will be useful,
11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13;;;; GNU General Public License for more details.
14;;;;
15;;;; You should have received a copy of the GNU General Public License
16;;;; along with this software; see the file COPYING. If not, write to
17;;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18;;;;
19\f
20
21;;; This file is the first thing loaded into Guile. It adds many mundane
22;;; definitions and a few that are interesting.
23;;;
24;;; The module system (hence the hierarchical namespace) are defined in this
25;;; file.
26;;;
27
28\f
29
30;; {Simple Debugging Tools}
31;;
32
33
34;; peek takes any number of arguments, writes them to the
35;; current ouput port, and returns the last argument.
36;; It is handy to wrap around an expression to look at
37;; a value each time is evaluated, e.g.:
38;;
39;; (+ 10 (troublesome-fn))
40;; => (+ 10 (pk 'troublesome-fn-returned (troublesome-fn)))
41;;
42
43(define (peek . stuff)
44 (newline)
45 (display ";;; ")
46 (write stuff)
47 (newline)
48 (car (last-pair stuff)))
49
50(define pk peek)
51
52(define (warn . stuff)
53 (with-output-to-port (current-error-port)
54 (lambda ()
55 (newline)
56 (display ";;; WARNING ")
57 (print stuff)
58 (newline)
59 (car (last-pair stuff)))))
60
61\f
62;;; {apply and call-with-current-continuation}
63;;;
64;;; These turn syntax, @apply and @call-with-current-continuation,
65;;; into procedures.
66;;;
67
68(set! apply (lambda (fun . args) (@apply fun (apply:nconc2last args))))
69(define (call-with-current-continuation proc) (@call-with-current-continuation proc))
70
71
72\f
73;;; {apply-to-args}
74;;;
75;;; apply-to-args is functionally redunant with apply and, worse,
76;;; is less general than apply since it only takes two arguments.
77;;;
78;;; On the other hand, apply-to-args is a syntacticly convenient way to
79;;; perform binding in many circumstances when the "let" family of
80;;; of forms don't cut it. E.g.:
81;;;
82;;; (apply-to-args (return-3d-mouse-coords)
83;;; (lambda (x y z)
84;;; ...))
85;;;
86
87(define (apply-to-args args fn) (apply fn args))
88
89\f
90;;; {Silly Naming Cleanups and Trivial Functions}
91;;;
92
0f2d19dd
JB
93(define (id x) x)
94(define < <?)
95(define <= <=?)
96(define = =?)
97(define > >?)
98(define >= >=?)
99(define (1+ n) (+ n 1))
100(define (-1+ n) (+ n -1))
101(define 1- -1+)
102(define return-it noop)
103(define (and=> value thunk) (and value (thunk value)))
104(define (make-hash-table k) (make-vector k '()))
105\f
106;;; {Integer Math}
107;;;
108
109(define (integer? x) (and (number? x) (= x (inexact->exact x))))
110
111(define (ipow-by-squaring x k acc proc)
112 (cond ((zero? k) acc)
113 ((= 1 k) (proc acc x))
114 (else (logical:ipow-by-squaring (proc x x)
115 (quotient k 2)
116 (if (even? k) acc (proc acc x))
117 proc))))
118
119(define string-character-length string-length)
120
121
122
123;; A convenience function for combining flag bits. Like logior, but
124;; handles the cases of 0 and 1 arguments.
125;;
126(define (flags . args)
127 (cond
128 ((null? args) 0)
129 ((null? (cdr args)) (car args))
130 (else (apply logior args))))
131
132\f
133;;; {Basic Port Code}
134;;;
135;;; Specificly, the parts of the low-level port code that are written in
136;;; Scheme rather than C.
137;;;
138;;; WARNING: the parts of this interface that refer to file ports
139;;; is going away. It would be gone already except that it is used
140;;; "internally" in a few places.
141;;;
142
143
144;; OPEN_READ, OPEN_WRITE, and OPEN_BOTH are used to request the proper
145;; mode to open files in. MSDOS does carraige return - newline
146;; translation if not opened in `b' mode.
147;;
148(define OPEN_READ (case (software-type)
149 ((MS-DOS WINDOWS ATARIST) "rb")
150 (else "r")))
151(define OPEN_WRITE (case (software-type)
152 ((MS-DOS WINDOWS ATARIST) "wb")
153 (else "w")))
154(define OPEN_BOTH (case (software-type)
155 ((MS-DOS WINDOWS ATARIST) "r+b")
156 (else "r+")))
157
8b13c6b3
GH
158(define *null-device* "/dev/null")
159
0f2d19dd 160(define (open-input-file str)
8b13c6b3 161 (open-file str OPEN_READ))
0f2d19dd
JB
162
163(define (open-output-file str)
8b13c6b3 164 (open-file str OPEN_WRITE))
0f2d19dd
JB
165
166(define (open-io-file str) (open-file str OPEN_BOTH))
167(define close-input-port close-port)
168(define close-output-port close-port)
169(define close-io-port close-port)
170
171(define (call-with-input-file str proc)
172 (let* ((file (open-input-file str))
173 (ans (proc file)))
174 (close-input-port file)
175 ans))
176
177(define (call-with-output-file str proc)
178 (let* ((file (open-output-file str))
179 (ans (proc file)))
180 (close-output-port file)
181 ans))
182
183(define (with-input-from-port port thunk)
184 (let* ((swaports (lambda () (set! port (set-current-input-port port)))))
185 (dynamic-wind swaports thunk swaports)))
186
187(define (with-output-to-port port thunk)
188 (let* ((swaports (lambda () (set! port (set-current-output-port port)))))
189 (dynamic-wind swaports thunk swaports)))
190
191(define (with-error-to-port port thunk)
192 (let* ((swaports (lambda () (set! port (set-current-error-port port)))))
193 (dynamic-wind swaports thunk swaports)))
194
195(define (with-input-from-file file thunk)
196 (let* ((nport (open-input-file file))
197 (ans (with-input-from-port nport thunk)))
198 (close-port nport)
199 ans))
200
201(define (with-output-to-file file thunk)
202 (let* ((nport (open-output-file file))
203 (ans (with-output-to-port nport thunk)))
204 (close-port nport)
205 ans))
206
207(define (with-error-to-file file thunk)
208 (let* ((nport (open-output-file file))
209 (ans (with-error-to-port nport thunk)))
210 (close-port nport)
211 ans))
212
213(define (with-input-from-string string thunk)
214 (call-with-input-string string
215 (lambda (p) (with-input-from-port p thunk))))
216
217(define (with-output-to-string thunk)
218 (call-with-output-string
219 (lambda (p) (with-output-to-port p thunk))))
220
221(define (with-error-to-string thunk)
222 (call-with-output-string
223 (lambda (p) (with-error-to-port p thunk))))
224
225(define the-eof-object (call-with-input-string "" (lambda (p) (read-char p))))
226
227
228\f
229;;; {Symbol Properties}
230;;;
231
232(define (symbol-property sym prop)
233 (let ((pair (assoc prop (symbol-pref sym))))
234 (and pair (cdr pair))))
235
236(define (set-symbol-property! sym prop val)
237 (let ((pair (assoc prop (symbol-pref sym))))
238 (if pair
239 (set-cdr! pair val)
240 (symbol-pset! sym (acons prop val (symbol-pref sym))))))
241
242(define (symbol-property-remove! sym prop)
243 (let ((pair (assoc prop (symbol-pref sym))))
244 (if pair
245 (symbol-pset! sym (delq! pair (symbol-pref sym))))))
246
247\f
248;;; {Arrays}
249;;;
250
251(begin
252 (define uniform-vector? array?)
253 (define make-uniform-vector dimensions->uniform-array)
254 ; (define uniform-vector-ref array-ref)
255 (define (uniform-vector-set! u i o)
256 (uniform-vector-set1! u o i))
257 (define uniform-vector-fill! array-fill!)
258 (define uniform-vector-read! uniform-array-read!)
259 (define uniform-vector-write uniform-array-write)
260
261 (define (make-array fill . args)
262 (dimensions->uniform-array args () fill))
263 (define (make-uniform-array prot . args)
264 (dimensions->uniform-array args prot))
265 (define (list->array ndim lst)
266 (list->uniform-array ndim '() lst))
267 (define (list->uniform-vector prot lst)
268 (list->uniform-array 1 prot lst))
269 (define (array-shape a)
270 (map (lambda (ind) (if (number? ind) (list 0 (+ -1 ind)) ind))
271 (array-dimensions a))))
272
273\f
274;;; {Keywords}
275;;;
276
277(define (symbol->keyword symbol)
278 (make-keyword-from-dash-symbol (symbol-append '- symbol)))
279
280(define (keyword->symbol kw)
281 (let ((sym (keyword-dash-symbol kw)))
282 (string->symbol (substring sym 1 (length sym)))))
283
284(define (kw-arg-ref args kw)
285 (let ((rem (member kw args)))
286 (and rem (pair? (cdr rem)) (cadr rem))))
287
288\f
289
290;;; {Print}
291;;;
292
293(define (print obj . args)
294 (let ((default-args (list (current-output-port) 0 0 default-print-style #f)))
295 (apply-to-args (append args (list-cdr-ref default-args (length args)))
296 (lambda (port depth length style table)
297 (cond
298 ((and table (print-table-ref table obj)) ((print-style-tag-hook style 'eq-val)
299 obj port depth length style table))
300 (else
301 (and table (print-table-add! table obj))
302 (cond
303 ((print-style-max-depth? style depth) ((print-style-excess-depth-hook style)))
304 ((print-style-max-length? style length) ((print-style-excess-length-hook style)))
305 (else ((print-style-hook style obj)
306 obj port depth length style table)))))))))
307
308(define (make-print-style) (make-vector 59))
309
310(define (extend-print-style! style utag printer) (hashq-set! style utag printer))
311
312(define (print-style-hook style obj)
313 (let ((type-tag (tag obj)))
314 (or (hashq-ref style type-tag)
315 (hashq-ref style (logand type-tag 255))
316 print-obj)))
317
318(define (print-style-tag-hook style type-tag)
319 (or (hashq-ref style type-tag)
320 print-obj))
321
322(define (print-style-max-depth? style d) #f)
323(define (print-style-max-length? style l) #f)
324(define (print-style-excess-length-hook style) (hashq-ref style 'excess-length-hook))
325(define (print-style-excess-depth-hook style) (hashq-ref style 'excess-depth-hook))
326
327(define (make-print-table) (make-vector 59))
328(define (print-table-ref table obj) (hashq-ref table obj))
329(define (print-table-add! table obj) (hashq-set! table obj (gensym 'ref)))
330
331(define (print-obj obj port depth length style table) (write obj port))
332
333(define (print-pair pair port depth length style table)
334 (if (= 0 length)
335 (display #\( port))
336
337 (print (car pair) port (+ 1 depth) 0 style table)
338
339 (cond
340 ((and (pair? (cdr pair))
341 (or (not table)
342 (not (print-table-ref table (cdr pair)))))
343
344 (display #\space port)
345 (print (cdr pair) port depth (+ 1 length) style table))
346
347 ((null? (cdr pair)) (display #\) port))
348
349 (else (display " . " port)
350 (print (cdr pair) port (+ 1 depth) 0 style table)
351 (display #\) port))))
352
353(define (print-vector obj port depth length style table)
354 (if (= 0 length)
355 (cond
074fa9cf 356 ((weak-key-hash-table? obj) (display "#wh(" port))
0f2d19dd
JB
357 ((weak-value-hash-table? obj) (display "#whv(" port))
358 ((doubly-weak-hash-table? obj) (display "#whd(" port))
359 (else (display "#(" port))))
360
361 (if (< length (vector-length obj))
362 (print (vector-ref obj length) port (+ 1 depth) 0 style table))
363
364 (cond
365 ((>= (+ 1 length) (vector-length obj)) (display #\) port))
366 (else (display #\space port)
367 (print obj port depth (+ 1 length) style table))))
368
369(define default-print-style (make-print-style))
370
371(extend-print-style! default-print-style utag_vector print-vector)
372(extend-print-style! default-print-style utag_wvect print-vector)
373(extend-print-style! default-print-style utag_pair print-pair)
374(extend-print-style! default-print-style 'eq-val
375 (lambda (obj port depth length style table)
376 (if (symbol? obj)
377 (display obj)
378 (begin
379 (display "##" port)
380 (display (print-table-ref table obj))))))
381
382\f
383;;; {Records}
384;;;
385
386(define record-type-vtable (make-vtable-vtable "prpr" 0))
387
388(define (record-type? obj)
389 (and (struct? obj) (eq? record-type-vtable (struct-vtable obj))))
390
391(define (make-record-type type-name fields . opt)
392 (let ((printer-fn (and opt (car opt))))
393 (let ((struct (make-struct record-type-vtable 0
394 (make-struct-layout (apply symbol-append (map (lambda (f) "pw") fields)))
395 type-name
396 (copy-tree fields))))
397 ;; !!! leaks printer functions
398 (if printer-fn
399 (extend-print-style! default-print-style
400 (logior utag_struct_base (ash (struct-vtable-tag struct) 8))
401 printer-fn))
402 struct)))
403
404(define (record-type-name obj)
405 (if (record-type? obj)
406 (struct-ref obj struct-vtable-offset)
407 (error 'not-a-record-type obj)))
408
409(define (record-type-fields obj)
410 (if (record-type? obj)
411 (struct-ref obj (+ 1 struct-vtable-offset))
412 (error 'not-a-record-type obj)))
413
414(define (record-constructor rtd . opt)
415 (let ((field-names (if opt (car opt) (record-type-fields rtd))))
416 (eval `(lambda ,field-names
417 (make-struct ',rtd 0 ,@(map (lambda (f)
418 (if (memq f field-names)
419 f
420 #f))
421 (record-type-fields rtd)))))))
422
423(define (record-predicate rtd)
424 (lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj)))))
425
426(define (record-accessor rtd field-name)
427 (let* ((pos (list-index (record-type-fields rtd) field-name)))
428 (if (not pos)
429 (error 'no-such-field field-name))
430 (eval `(lambda (obj)
431 (and (eq? ',rtd (record-type-descriptor obj))
432 (struct-ref obj ,pos))))))
433
434(define (record-modifier rtd field-name)
435 (let* ((pos (list-index (record-type-fields rtd) field-name)))
436 (if (not pos)
437 (error 'no-such-field field-name))
438 (eval `(lambda (obj val)
439 (and (eq? ',rtd (record-type-descriptor obj))
440 (struct-set! obj ,pos val))))))
441
442
443(define (record? obj)
444 (and (struct? obj) (record-type? (struct-vtable obj))))
445
446(define (record-type-descriptor obj)
447 (if (struct? obj)
448 (struct-vtable obj)
449 (error 'not-a-record obj)))
450
451\f
452;;; {Booleans}
453;;;
454
455(define (->bool x) (not (not x)))
456
457\f
458;;; {Symbols}
459;;;
460
461(define (symbol-append . args)
462 (string->symbol (apply string-append args)))
463
464(define (list->symbol . args)
465 (string->symbol (apply list->string args)))
466
467(define (symbol . args)
468 (string->symbol (apply string args)))
469
470(define (obarray-symbol-append ob . args)
471 (string->obarray-symbol (apply string-append ob args)))
472
473(define obarray-gensym
474 (let ((n -1))
475 (lambda (obarray . opt)
476 (if (null? opt)
477 (set! opt '(%%gensym)))
478 (let loop ((proposed-name (apply string-append opt)))
479 (if (string->obarray-symbol obarray proposed-name #t)
480 (loop (apply string-append (append opt (begin (set! n (1+ n)) (list (number->string n))))))
481 (string->obarray-symbol obarray proposed-name))))))
482
483(define (gensym . args) (apply obarray-gensym #f args))
484
485\f
486;;; {Lists}
487;;;
488
489(define (list-index l k)
490 (let loop ((n 0)
491 (l l))
492 (and (not (null? l))
493 (if (eq? (car l) k)
494 n
495 (loop (+ n 1) (cdr l))))))
496
497(define (make-list n init)
498 (let loop ((answer '())
499 (n n))
500 (if (<= n 0)
501 answer
502 (loop (cons init answer) (- n 1)))))
503
504
505\f
506;;; {and-map, or-map, and map-in-order}
507;;;
508;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
509;;; (or-map fn lst) is like (or (fn (car lst)) (fn (cadr lst)) (fn...) ...)
510;;; (map-in-order fn lst) is like (map fn lst) but definately in order of lst.
511;;;
512
513;; and-map f l
514;;
515;; Apply f to successive elements of l until exhaustion or f returns #f.
516;; If returning early, return #f. Otherwise, return the last value returned
517;; by f. If f has never been called because l is empty, return #t.
518;;
519(define (and-map f lst)
520 (let loop ((result #t)
521 (l lst))
522 (and result
523 (or (and (null? l)
524 result)
525 (loop (f (car l)) (cdr l))))))
526
527;; or-map f l
528;;
529;; Apply f to successive elements of l until exhaustion or while f returns #f.
530;; If returning early, return the return value of f.
531;;
532(define (or-map f lst)
533 (let loop ((result #f)
534 (l lst))
535 (or result
536 (and (not (null? l))
537 (loop (f (car l)) (cdr l))))))
538
539;; map-in-order
540;;
541;; Like map, but guaranteed to process the list in order.
542;;
543(define (map-in-order fn l)
544 (if (null? l)
545 '()
546 (cons (fn (car l))
547 (map-in-order fn (cdr l)))))
548
549\f
550;;; {Files}
551;;; !!!! these should be implemented using Tcl commands, not fports.
552;;;
553
554(define (file-exists? str)
8b13c6b3
GH
555 ;; we don't have false-if-exception (or defmacro) yet.
556 (let ((port (catch #t (lambda () (open-file str OPEN_READ))
557 (lambda args #f))))
0f2d19dd
JB
558 (if port (begin (close-port port) #t)
559 #f)))
560
561(define (file-is-directory? str)
8b13c6b3
GH
562 (let ((port (catch #t (lambda () (open-file (string-append str "/.")
563 OPEN_READ))
564 (lambda args #f))))
0f2d19dd
JB
565 (if port (begin (close-port port) #t)
566 #f)))
567
568(define (has-suffix? str suffix)
569 (let ((sufl (string-length suffix))
570 (sl (string-length str)))
571 (and (> sl sufl)
572 (string=? (substring str (- sl sufl) sl) suffix))))
573
574
575
576\f
577;;; {Error Handling}
578;;;
579
0f2d19dd 580(define (error . args)
2194b6f0
GH
581 (if (null? args)
582 (throw 'error #f "?" #f #f)
583 (let loop ((msg "%s")
584 (rest (cdr args)))
585 (if (not (null? rest))
586 (loop (string-append msg " %S")
587 (cdr rest))
588 (throw 'error #f msg args #f)))))
0f2d19dd
JB
589
590;; %%bad-throw is the hook that is called upon a throw to a an unhandled
591;; key. If the key has a default handler (a throw-handler-default property),
592;; it is applied to the throw.
593;;
594(define (%%bad-throw key . args)
595 (let ((default (symbol-property key 'throw-handler-default)))
596 (or (and default (apply default key args))
2194b6f0 597 (apply error "unhandled-exception:" key args))))
0f2d19dd 598
2194b6f0
GH
599;; mostly obsolete.
600;; A number of internally defined error types were represented
0f2d19dd
JB
601;; as integers. Here is the mapping to symbolic names
602;; and error messages.
603;;
2194b6f0
GH
604;(define %%system-errors
605; '((-1 UNKNOWN "Unknown error")
606; (0 ARGn "Wrong type argument to ")
607; (1 ARG1 "Wrong type argument in position 1 to ")
608; (2 ARG2 "Wrong type argument in position 2 to ")
609; (3 ARG3 "Wrong type argument in position 3 to ")
610; (4 ARG4 "Wrong type argument in position 4 to ")
611; (5 ARG5 "Wrong type argument in position 5 to ")
612; (6 ARG5 "Wrong type argument in position 5 to ")
613; (7 ARG5 "Wrong type argument in position 5 to ")
614; (8 WNA "Wrong number of arguments to ")
615; (9 OVFLOW "Numerical overflow to ")
616; (10 OUTOFRANGE "Argument out of range to ")
617; (11 NALLOC "Could not allocate to ")
618; (12 STACK_OVFLOW "Stack overflow")
619; (13 EXIT "Exit (internal error?).")
620; (14 HUP_SIGNAL "hang-up")
621; (15 INT_SIGNAL "user interrupt")
622; (16 FPE_SIGNAL "arithmetic error")
623; (17 BUS_SIGNAL "bus error")
624; (18 SEGV_SIGNAL "segmentation violation")
625; (19 ALRM_SIGNAL "alarm")
626; (20 GC_SIGNAL "gc")
627; (21 TICK_SIGNAL "tick")))
0f2d19dd
JB
628
629
630(define (timer-thunk) #t)
631(define (gc-thunk) #t)
632(define (alarm-thunk) #t)
633
634(define (signal-handler n)
2194b6f0
GH
635 (let* (
636 ;; these numbers are set in libguile, not the same as those
637 ;; interned in posix.c.
638 ;;
639 (signal-messages `((14 . "hang-up")
640 (15 . "user interrupt")
641 (16 . "arithmetic error")
642 (17 . "bus error")
643 (18 . "segmentation violation"))))
644 (cond
645 ((= n 21) (unmask-signals) (timer-thunk))
646 ((= n 20) (unmask-signals) (gc-thunk))
647 ((= n 19) (unmask-signals) (alarm-thunk))
648 (else (unmask-signals)
649 (let ((sig-pair (assoc n signal-messages)))
650 (throw 'error-signal #f
651 (cdr (or sig-pair
652 (cons n "Unknow signal: %s")))
653 (if sig-pair
654 #f
655 (list n))
656 (list n)))))))
657
658(define display-error-message
659 (lambda (message args port)
660 (if (or (not (list? args))
661 (null? args))
662 (display message port)
663 (let ((len (string-length message)))
664 (cond ((< len 2)
665 (display message port))
666 ((string=? (substring message 0 2)
667 "%s")
668 (display (car args) port)
669 (display-error-message (substring message 2 len)
670 (cdr args)
671 port))
672 ((string=? (substring message 0 2)
673 "%S")
674 (write (car args) port)
675 (display-error-message (substring message 2 len)
676 (cdr args)
677 port))
678 (else
679 (display (substring message 0 1)
680 port)
681 (display-error-message (substring message 1 len)
682 args
683 port)))))))
684
685;; The default handler for built-in error types when thrown by their
686;; symbolic names.
7cb1d4d3 687(define (%%handle-system-error key . arg-list)
2194b6f0
GH
688 (let ((cep (current-error-port)))
689 (cond ((not (= (length arg-list) 4))
690 (display "ERROR: bad error throw: " cep)
691 (write arg-list cep))
692 (else
693 (let ((subr (car arg-list))
694 (message (cadr arg-list))
695 (args (or (caddr arg-list)
696 '()))
697 (rest (or (cadddr arg-list)
698 '())))
699 (display "ERROR: " cep)
700 (cond (subr
701 (display subr cep)
702 (display ": " cep)))
703 (cond ((list? args)
704 (display-error-message message args cep))
705 (else
706 (display message cep)
707 (display " (bad message args)" cep))))))
708 (newline cep)
709 (force-output cep)
710 (throw 'abort key)))
711
712;; associate error symbols with %%handle-system-error.
713(let loop ((keys '(error error-signal system-error numerical-overflow
714 out-of-range wrong-type-arg wrong-number-of-args
715 memory-allocation-error stack-overflow
716 misc-error)))
e1724d20
GH
717 (cond ((not (null? keys))
718 (set-symbol-property! (car keys)
719 'throw-handler-default
720 %%handle-system-error)
721 (loop (cdr keys)))))
0f2d19dd
JB
722
723\f
02b754d3
GH
724(define (getgrnam name) (getgr name))
725(define (getgrgid id) (getgr id))
726(define (gethostbyaddr addr) (gethost addr))
727(define (gethostbyname name) (gethost name))
728(define (getnetbyaddr addr) (getnet addr))
729(define (getnetbyname name) (getnet name))
730(define (getprotobyname name) (getproto name))
731(define (getprotobynumber addr) (getproto addr))
732(define (getpwnam name) (getpw name))
733(define (getpwuid uid) (getpw uid))
734(define (getservbyname name proto) (%getserv name proto))
735(define (getservbyport port proto) (%getserv port proto))
0f2d19dd
JB
736(define (endgrent) (setgr))
737(define (endhostent) (sethost))
738(define (endnetent) (setnet))
739(define (endprotoent) (setproto))
740(define (endpwent) (setpw))
741(define (endservent) (setserv))
742(define (file-position . args) (apply ftell args))
743(define (file-set-position . args) (apply fseek args))
02b754d3
GH
744(define (getgrent) (getgr))
745(define (gethostent) (gethost))
746(define (getnetent) (getnet))
747(define (getprotoent) (getproto))
748(define (getpwent) (getpw))
749(define (getservent) (getserv))
0f2d19dd
JB
750(define (reopen-file . args) (apply freopen args))
751(define (setgrent arg) (setgr arg))
752(define (sethostent arg) (sethost arg))
753(define (setnetent arg) (setnet arg))
754(define (setprotoent arg) (setproto arg))
755(define (setpwent arg) (setpw arg))
756(define (setservent arg) (setserv arg))
8b13c6b3 757
02b754d3 758(define (move->fdes port fd)
8b13c6b3
GH
759 (primitive-move->fdes port fd)
760 (set-port-revealed! port 1)
761 port)
762
763(define (release-port-handle port)
764 (let ((revealed (port-revealed port)))
765 (if (> revealed 0)
766 (set-port-revealed! port (- revealed 1)))))
0f2d19dd
JB
767
768\f
769;;; {Load Paths}
770;;;
771
0f2d19dd
JB
772;;; Here for backward compatability
773;;
774(define scheme-file-suffix (lambda () ".scm"))
775
3cab8392
JB
776(define (in-vicinity vicinity file)
777 (let ((tail (let ((len (string-length vicinity)))
778 (if (zero? len) #f
779 (string-ref vicinity (- len 1))))))
780 (string-append vicinity
781 (if (eq? tail #\/) "" "/")
782 file)))
02ceadb8 783
0f2d19dd
JB
784\f
785;;; {try-load}
786;;;
787
788(define (try-load-with-path file-name path)
789 (or-map (lambda (d)
790 (let ((f (in-vicinity d file-name)))
791 (and (not (file-is-directory? f))
792 (%try-load f #t read-sharp))))
793 path))
794
795(define (try-load name)
796 (if (eval '(defined? %load-path))
797 (try-load-with-path name (eval '%load-path))
798 (%try-load name #t read-sharp)))
799\f
800;;; {Load}
801;;;
802
803(define %load-verbosely #t)
804(define (assert-load-verbosity v) (set! %load-verbosely v))
805(define %load-indent -2)
806
807(define (%load f)
808 (current-module)
809 (or (and (not (file-is-directory? f))
810 (%try-load f #t read-sharp))
811 (and (not (has-suffix? f (scheme-file-suffix)))
812 (%try-load (string-append f (scheme-file-suffix)) #t read-sharp))))
813
814(define (%load-announce file)
815 (if %load-verbosely
816 (with-output-to-port (current-error-port)
817 (lambda ()
818 (display ";;; ")
819 (display (make-string %load-indent #\ ))
820 (display "loading ")
821 (display file)
822 (display "...")
823 (newline)
824 (force-output)))))
825
826(define (%load-announce-win file)
827 (if %load-verbosely
828 (with-output-to-port (current-error-port)
829 (lambda ()
830 (display ";;; ")
831 (display (make-string %load-indent #\ ))
832 (display "...loaded ")
833 (display file)
834 (display ".")
835 (newline)
836 (force-output)))))
837
838(define (%load-announce-lossage file path)
839 (if %load-verbosely
840 (with-output-to-port (current-error-port)
841 (lambda ()
842 (display ";;; ")
843 (display (make-string %load-indent #\ ))
844 (display "...COULD NOT LOAD ")
845 (display file)
846 (display " from ")
847 (write path)
848 (newline)
849 (force-output))))
850 (throw 'could-not-load file path))
851
852
853(define (load-with-path name path)
854 (define (do-load)
855 (%load-announce name)
856 (if (not (or-map (lambda (d)
857 (if (%load (in-vicinity d name))
858 (begin
859 (%load-announce-win (in-vicinity d name))
860 #t)
861 #f))
862 path))
863 (%load-announce-lossage name path)))
864
865 (let ((indent %load-indent))
866 (dynamic-wind
867 (lambda () (set! %load-indent (modulo (+ indent 2) 16)))
868 do-load
869 (lambda () (set! %load-indent indent))))
870 #t)
871
872
873(define (load name)
874 (if (eval '(defined? %load-path))
875 (load-with-path name (eval '%load-path))
876 (load-with-path name '())))
877
878
879\f
880;;; {Transcendental Functions}
881;;;
882;;; Derived from "Transcen.scm", Complex trancendental functions for SCM.
883;;; Copyright (C) 1992, 1993 Jerry D. Hedden.
884;;; See the file `COPYING' for terms applying to this program.
885;;;
886
887(define (exp z)
888 (if (real? z) ($exp z)
889 (make-polar ($exp (real-part z)) (imag-part z))))
890
891(define (log z)
892 (if (and (real? z) (>= z 0))
893 ($log z)
894 (make-rectangular ($log (magnitude z)) (angle z))))
895
896(define (sqrt z)
897 (if (real? z)
898 (if (negative? z) (make-rectangular 0 ($sqrt (- z)))
899 ($sqrt z))
900 (make-polar ($sqrt (magnitude z)) (/ (angle z) 2))))
901
902(define expt
903 (let ((integer-expt integer-expt))
904 (lambda (z1 z2)
905 (cond ((exact? z2)
906 (integer-expt z1 z2))
907 ((and (real? z2) (real? z1) (>= z1 0))
908 ($expt z1 z2))
909 (else
910 (exp (* z2 (log z1))))))))
911
912(define (sinh z)
913 (if (real? z) ($sinh z)
914 (let ((x (real-part z)) (y (imag-part z)))
915 (make-rectangular (* ($sinh x) ($cos y))
916 (* ($cosh x) ($sin y))))))
917(define (cosh z)
918 (if (real? z) ($cosh z)
919 (let ((x (real-part z)) (y (imag-part z)))
920 (make-rectangular (* ($cosh x) ($cos y))
921 (* ($sinh x) ($sin y))))))
922(define (tanh z)
923 (if (real? z) ($tanh z)
924 (let* ((x (* 2 (real-part z)))
925 (y (* 2 (imag-part z)))
926 (w (+ ($cosh x) ($cos y))))
927 (make-rectangular (/ ($sinh x) w) (/ ($sin y) w)))))
928
929(define (asinh z)
930 (if (real? z) ($asinh z)
931 (log (+ z (sqrt (+ (* z z) 1))))))
932
933(define (acosh z)
934 (if (and (real? z) (>= z 1))
935 ($acosh z)
936 (log (+ z (sqrt (- (* z z) 1))))))
937
938(define (atanh z)
939 (if (and (real? z) (> z -1) (< z 1))
940 ($atanh z)
941 (/ (log (/ (+ 1 z) (- 1 z))) 2)))
942
943(define (sin z)
944 (if (real? z) ($sin z)
945 (let ((x (real-part z)) (y (imag-part z)))
946 (make-rectangular (* ($sin x) ($cosh y))
947 (* ($cos x) ($sinh y))))))
948(define (cos z)
949 (if (real? z) ($cos z)
950 (let ((x (real-part z)) (y (imag-part z)))
951 (make-rectangular (* ($cos x) ($cosh y))
952 (- (* ($sin x) ($sinh y)))))))
953(define (tan z)
954 (if (real? z) ($tan z)
955 (let* ((x (* 2 (real-part z)))
956 (y (* 2 (imag-part z)))
957 (w (+ ($cos x) ($cosh y))))
958 (make-rectangular (/ ($sin x) w) (/ ($sinh y) w)))))
959
960(define (asin z)
961 (if (and (real? z) (>= z -1) (<= z 1))
962 ($asin z)
963 (* -i (asinh (* +i z)))))
964
965(define (acos z)
966 (if (and (real? z) (>= z -1) (<= z 1))
967 ($acos z)
968 (+ (/ (angle -1) 2) (* +i (asinh (* +i z))))))
969
970(define (atan z . y)
971 (if (null? y)
972 (if (real? z) ($atan z)
973 (/ (log (/ (- +i z) (+ +i z))) +2i))
974 ($atan2 z (car y))))
975
976(set! abs magnitude)
977
978\f
979;;; {User Settable Hooks}
980;;;
981;;; Parts of the C code check the bindings of these variables.
982;;;
983
984(define ticks-interrupt #f)
985(define user-interrupt #f)
986(define alarm-interrupt #f)
987(define out-of-storage #f)
988(define could-not-open #f)
989(define end-of-program #f)
990(define hang-up #f)
991(define arithmetic-error #f)
992(define read-sharp #f)
993
994\f
995
996;;; {Reader Extensions}
997;;;
998
999;;; Reader code for various "#c" forms.
1000;;;
1001
1002(define (parse-path-symbol s)
1003 (define (seperate-fields-discarding-char ch str ret)
1004 (let loop ((fields '())
1005 (str str))
1006 (cond
1007 ((string-rindex str ch)
1008 => (lambda (pos) (loop (cons (make-shared-substring str (+ 1 pos)) fields)
1009 (make-shared-substring str 0 pos))))
1010 (else (ret (cons str fields))))))
1011 (seperate-fields-discarding-char #\/
1012 s
1013 (lambda (fields)
1014 (map string->symbol fields))))
1015
1016
1017(define (%read-sharp c port)
1018 (define (barf)
1019 (error "unknown # object" c))
1020
1021 (case c
1022 ((#\/) (let ((look (peek-char port)))
1023 (if (or (eof-object? look)
1024 (and (char? look)
1025 (or (char-whitespace? look)
1026 (string-index ")" look))))
1027 '()
1028 (parse-path-symbol (read port #t read-sharp)))))
1029 ((#\') (read port #t read-sharp))
1030 ((#\.) (eval (read port #t read-sharp)))
1031 ((#\b) (read:uniform-vector #t port))
1032 ((#\a) (read:uniform-vector #\a port))
1033 ((#\u) (read:uniform-vector 1 port))
1034 ((#\e) (read:uniform-vector -1 port))
1035 ((#\s) (read:uniform-vector 1.0 port))
1036 ((#\i) (read:uniform-vector 1/3 port))
1037 ((#\c) (read:uniform-vector 0+i port))
1038 ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
1039 (read:array c port))
1040 ((#\!) (if (= 1 (line-number))
1041 (let skip () (if (eq? #\newline (peek-char port))
1042 (read port #t read-sharp)
1043 (begin (read-char port) (skip))))
1044 (barf)))
1045 (else (barf))))
1046
1047(define (read:array digit port)
1048 (define chr0 (char->integer #\0))
1049 (let ((rank (let readnum ((val (- (char->integer digit) chr0)))
1050 (if (char-numeric? (peek-char port))
1051 (readnum (+ (* 10 val)
1052 (- (char->integer (read-char port)) chr0)))
1053 val)))
1054 (prot (if (eq? #\( (peek-char port))
1055 '()
1056 (let ((c (read-char port)))
1057 (case c ((#\b) #t)
1058 ((#\a) #\a)
1059 ((#\u) 1)
1060 ((#\e) -1)
1061 ((#\s) 1.0)
1062 ((#\i) 1/3)
1063 ((#\c) 0+i)
1064 (else (error "read:array unknown option " c)))))))
1065 (if (eq? (peek-char port) #\()
1066 (list->uniform-array rank prot (read port #t read-sharp))
1067 (error "read:array list not found"))))
1068
1069(define (read:uniform-vector proto port)
1070 (if (eq? #\( (peek-char port))
1071 (list->uniform-array 1 proto (read port #t read-sharp))
1072 (error "read:uniform-vector list not found")))
1073
1074
1075(define read-sharp (lambda a (apply %read-sharp a)))
1076
1077
1078\f
1079;;; {Dynamic Roots}
1080;;;
1081
1082; mystery integers passed dynamic root error handlers
1083(define repl-quit -1)
1084(define repl-abort -2)
1085
1086
1087\f
1088;;; {Command Line Options}
1089;;;
1090
1091(define (get-option argv kw-opts kw-args return)
1092 (cond
1093 ((null? argv)
1094 (return #f #f argv))
1095
1096 ((or (not (eq? #\- (string-ref (car argv) 0)))
1097 (eq? (string-length (car argv)) 1))
1098 (return 'normal-arg (car argv) (cdr argv)))
1099
1100 ((eq? #\- (string-ref (car argv) 1))
1101 (let* ((kw-arg-pos (or (string-index (car argv) #\=)
1102 (string-length (car argv))))
1103 (kw (symbol->keyword (substring (car argv) 2 kw-arg-pos)))
1104 (kw-opt? (member kw kw-opts))
1105 (kw-arg? (member kw kw-args))
1106 (arg (or (and (not (eq? kw-arg-pos (string-length (car argv))))
1107 (substring (car argv)
1108 (+ kw-arg-pos 1)
1109 (string-length (car argv))))
1110 (and kw-arg?
1111 (begin (set! argv (cdr argv)) (car argv))))))
1112 (if (or kw-opt? kw-arg?)
1113 (return kw arg (cdr argv))
1114 (return 'usage-error kw (cdr argv)))))
1115
1116 (else
1117 (let* ((char (substring (car argv) 1 2))
1118 (kw (symbol->keyword char)))
1119 (cond
1120
1121 ((member kw kw-opts)
1122 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
1123 (new-argv (if (= 0 (string-length rest-car))
1124 (cdr argv)
1125 (cons (string-append "-" rest-car) (cdr argv)))))
1126 (return kw #f new-argv)))
1127
1128 ((member kw kw-args)
1129 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
1130 (arg (if (= 0 (string-length rest-car))
1131 (cadr argv)
1132 rest-car))
1133 (new-argv (if (= 0 (string-length rest-car))
1134 (cddr argv)
1135 (cdr argv))))
1136 (return kw arg new-argv)))
1137
1138 (else (return 'usage-error kw argv)))))))
1139
1140(define (for-next-option proc argv kw-opts kw-args)
1141 (let loop ((argv argv))
1142 (get-option argv kw-opts kw-args
1143 (lambda (opt opt-arg argv)
1144 (and opt (proc opt opt-arg argv loop))))))
1145
1146(define (display-usage-report kw-desc)
1147 (for-each
1148 (lambda (kw)
1149 (or (eq? (car kw) #t)
1150 (eq? (car kw) 'else)
1151 (let* ((opt-desc kw)
1152 (help (cadr opt-desc))
1153 (opts (car opt-desc))
1154 (opts-proper (if (string? (car opts)) (cdr opts) opts))
1155 (arg-name (if (string? (car opts))
1156 (string-append "<" (car opts) ">")
1157 ""))
1158 (left-part (string-append
1159 (with-output-to-string
1160 (lambda ()
1161 (map (lambda (x) (display (keyword-symbol x)) (display " "))
1162 opts-proper)))
1163 arg-name))
1164 (middle-part (if (and (< (length left-part) 30)
1165 (< (length help) 40))
1166 (make-string (- 30 (length left-part)) #\ )
1167 "\n\t")))
1168 (display left-part)
1169 (display middle-part)
1170 (display help)
1171 (newline))))
1172 kw-desc))
1173
1174
1175
1176(define (delq-all! obj l)
1177 (let ((answer (cons '() l)))
1178 (let loop ((pos answer))
1179 (cond
1180 ((null? (cdr pos)) (cdr answer))
1181 ((eq? (cadr pos) obj) (set-cdr! pos (cddr pos))
1182 (loop pos))
1183 (else (loop (cdr pos)))))))
1184
1185(define (transform-usage-lambda cases)
1186 (let* ((raw-usage (delq! 'else (map car cases)))
1187 (usage-sans-specials (map (lambda (x)
1188 (or (and (not (list? x)) x)
1189 (and (symbol? (car x)) #t)
1190 (and (boolean? (car x)) #t)
1191 x))
1192 raw-usage))
1193 (usage-desc (delq-all! #t usage-sans-specials))
1194 (kw-desc (map car usage-desc))
1195 (kw-opts (apply append (map (lambda (x) (and (not (string? (car x))) x)) kw-desc)))
1196 (kw-args (apply append (map (lambda (x) (and (string? (car x)) (cdr x))) kw-desc)))
1197 (transmogrified-cases (map (lambda (case)
1198 (cons (let ((opts (car case)))
1199 (if (or (boolean? opts) (eq? 'else opts))
1200 opts
1201 (cond
1202 ((symbol? (car opts)) opts)
1203 ((boolean? (car opts)) opts)
1204 ((string? (caar opts)) (cdar opts))
1205 (else (car opts)))))
1206 (cdr case)))
1207 cases)))
1208 `(let ((%display-usage (lambda () (display-usage-report ',usage-desc))))
1209 (lambda (%argv)
1210 (let %next-arg ((%argv %argv))
1211 (get-option %argv
1212 ',kw-opts
1213 ',kw-args
1214 (lambda (%opt %arg %new-argv)
1215 (case %opt
1216 ,@ transmogrified-cases))))))))
1217
1218
1219\f
1220
1221;;; {Low Level Modules}
1222;;;
1223;;; These are the low level data structures for modules.
1224;;;
1225;;; !!! warning: The interface to lazy binder procedures is going
1226;;; to be changed in an incompatible way to permit all the basic
1227;;; module ops to be virtualized.
1228;;;
1229;;; (make-module size use-list lazy-binding-proc) => module
1230;;; module-{obarray,uses,binder}[|-set!]
1231;;; (module? obj) => [#t|#f]
1232;;; (module-locally-bound? module symbol) => [#t|#f]
1233;;; (module-bound? module symbol) => [#t|#f]
1234;;; (module-symbol-locally-interned? module symbol) => [#t|#f]
1235;;; (module-symbol-interned? module symbol) => [#t|#f]
1236;;; (module-local-variable module symbol) => [#<variable ...> | #f]
1237;;; (module-variable module symbol) => [#<variable ...> | #f]
1238;;; (module-symbol-binding module symbol opt-value)
1239;;; => [ <obj> | opt-value | an error occurs ]
1240;;; (module-make-local-var! module symbol) => #<variable...>
1241;;; (module-add! module symbol var) => unspecified
1242;;; (module-remove! module symbol) => unspecified
1243;;; (module-for-each proc module) => unspecified
1244;;; (make-scm-module) => module ; a lazy copy of the symhash module
1245;;; (set-current-module module) => unspecified
1246;;; (current-module) => #<module...>
1247;;;
1248;;;
1249
1250\f
1251;; This is how modules are printed.
1252;; You can re-define it.
1253;;
1254(define (%print-module mod port depth length style table)
1255 (display "#<" port)
1256 (display (or (module-kind mod) "module") port)
1257 (let ((name (module-name mod)))
1258 (if name
1259 (begin
1260 (display " " port)
1261 (display name port))))
1262 (display " " port)
1263 (display (number->string (object-address mod) 16) port)
1264 (display ">" port))
1265
1266;; module-type
1267;;
1268;; A module is characterized by an obarray in which local symbols
1269;; are interned, a list of modules, "uses", from which non-local
1270;; bindings can be inherited, and an optional lazy-binder which
1271;; is a (THUNK module symbol) which, as a last resort, can provide
1272;; bindings that would otherwise not be found locally in the module.
1273;;
1274(define module-type
1275 (make-record-type 'module '(obarray uses binder eval-thunk name kind) %print-module))
1276
1277;; make-module &opt size uses
1278;;
1279;; Create a new module, perhaps with a particular size of obarray
1280;; or initial uses list.
1281;;
1282(define module-constructor (record-constructor module-type))
1283
1284(define make-module
1285 (lambda args
1286 (let* ((size 1021)
1287 (uses '())
1288 (binder #f)
1289 (answer #f)
1290 (eval-thunk
1291 (lambda (symbol define?)
1292 (if define?
1293 (module-make-local-var! answer symbol)
1294 (module-variable answer symbol)))))
1295
1296 (if (> (length args) 0)
1297 (begin
1298 (set! size (or (car args) size))
1299 (set! args (cdr args))))
1300
1301 (if (> (length args) 0)
1302 (begin
1303 (set! uses (or (car args) uses))
1304 (set! args (cdr args))))
1305
1306 (if (> (length args) 0)
1307 (begin
1308 (set! binder (or (car args) binder))
1309 (set! args (cdr args))))
1310
1311 (if (not (null? args))
1312 (error "Too many args to make-module." args))
1313
1314 (if (not (integer? size))
1315 (error "Illegal size to make-module." size))
1316
1317 (and (list? uses)
1318 (or (and-map module? uses)
1319 (error "Incorrect use list." uses)))
1320
1321 (if (and binder (not (procedure? binder)))
1322 (error
1323 "Lazy-binder expected to be a procedure or #f." binder))
1324
1325 (set! answer
1326 (module-constructor (make-vector size '())
1327 uses
1328 binder
1329 eval-thunk
1330 #f
1331 #f))
1332 answer)))
1333
1334(define module-obarray (record-accessor module-type 'obarray))
1335(define set-module-obarray! (record-modifier module-type 'obarray))
1336(define module-uses (record-accessor module-type 'uses))
1337(define set-module-uses! (record-modifier module-type 'uses))
1338(define module-binder (record-accessor module-type 'binder))
1339(define set-module-binder! (record-modifier module-type 'binder))
1340(define module-eval-thunk (record-accessor module-type 'eval-thunk))
1341(define set-module-eval-thunk! (record-modifier module-type 'eval-thunk))
1342(define module-name (record-accessor module-type 'name))
1343(define set-module-name! (record-modifier module-type 'name))
1344(define module-kind (record-accessor module-type 'kind))
1345(define set-module-kind! (record-modifier module-type 'kind))
1346(define module? (record-predicate module-type))
1347
1348(define (eval-in-module exp module)
1349 (eval2 exp (module-eval-thunk module)))
1350
1351\f
1352;;; {Module Searching in General}
1353;;;
1354;;; We sometimes want to look for properties of a symbol
1355;;; just within the obarray of one module. If the property
1356;;; holds, then it is said to hold ``locally'' as in, ``The symbol
1357;;; DISPLAY is locally rebound in the module `safe-guile'.''
1358;;;
1359;;;
1360;;; Other times, we want to test for a symbol property in the obarray
1361;;; of M and, if it is not found there, try each of the modules in the
1362;;; uses list of M. This is the normal way of testing for some
1363;;; property, so we state these properties without qualification as
1364;;; in: ``The symbol 'fnord is interned in module M because it is
1365;;; interned locally in module M2 which is a member of the uses list
1366;;; of M.''
1367;;;
1368
1369;; module-search fn m
1370;;
1371;; return the first non-#f result of FN applied to M and then to
1372;; the modules in the uses of m, and so on recursively. If all applications
1373;; return #f, then so does this function.
1374;;
1375(define (module-search fn m v)
1376 (define (loop pos)
1377 (and (pair? pos)
1378 (or (module-search fn (car pos) v)
1379 (loop (cdr pos)))))
1380 (or (fn m v)
1381 (loop (module-uses m))))
1382
1383
1384;;; {Is a symbol bound in a module?}
1385;;;
1386;;; Symbol S in Module M is bound if S is interned in M and if the binding
1387;;; of S in M has been set to some well-defined value.
1388;;;
1389
1390;; module-locally-bound? module symbol
1391;;
1392;; Is a symbol bound (interned and defined) locally in a given module?
1393;;
1394(define (module-locally-bound? m v)
1395 (let ((var (module-local-variable m v)))
1396 (and var
1397 (variable-bound? var))))
1398
1399;; module-bound? module symbol
1400;;
1401;; Is a symbol bound (interned and defined) anywhere in a given module
1402;; or its uses?
1403;;
1404(define (module-bound? m v)
1405 (module-search module-locally-bound? m v))
1406
1407;;; {Is a symbol interned in a module?}
1408;;;
1409;;; Symbol S in Module M is interned if S occurs in
1410;;; of S in M has been set to some well-defined value.
1411;;;
1412;;; It is possible to intern a symbol in a module without providing
1413;;; an initial binding for the corresponding variable. This is done
1414;;; with:
1415;;; (module-add! module symbol (make-undefined-variable))
1416;;;
1417;;; In that case, the symbol is interned in the module, but not
1418;;; bound there. The unbound symbol shadows any binding for that
1419;;; symbol that might otherwise be inherited from a member of the uses list.
1420;;;
1421
1422(define (module-obarray-get-handle ob key)
1423 ((if (symbol? key) hashq-get-handle hash-get-handle) ob key))
1424
1425(define (module-obarray-ref ob key)
1426 ((if (symbol? key) hashq-ref hash-ref) ob key))
1427
1428(define (module-obarray-set! ob key val)
1429 ((if (symbol? key) hashq-set! hash-set!) ob key val))
1430
1431(define (module-obarray-remove! ob key)
1432 ((if (symbol? key) hashq-remove! hash-remove!) ob key))
1433
1434;; module-symbol-locally-interned? module symbol
1435;;
1436;; is a symbol interned (not neccessarily defined) locally in a given module
1437;; or its uses? Interned symbols shadow inherited bindings even if
1438;; they are not themselves bound to a defined value.
1439;;
1440(define (module-symbol-locally-interned? m v)
1441 (not (not (module-obarray-get-handle (module-obarray m) v))))
1442
1443;; module-symbol-interned? module symbol
1444;;
1445;; is a symbol interned (not neccessarily defined) anywhere in a given module
1446;; or its uses? Interned symbols shadow inherited bindings even if
1447;; they are not themselves bound to a defined value.
1448;;
1449(define (module-symbol-interned? m v)
1450 (module-search module-symbol-locally-interned? m v))
1451
1452
1453;;; {Mapping modules x symbols --> variables}
1454;;;
1455
1456;; module-local-variable module symbol
1457;; return the local variable associated with a MODULE and SYMBOL.
1458;;
1459;;; This function is very important. It is the only function that can
1460;;; return a variable from a module other than the mutators that store
1461;;; new variables in modules. Therefore, this function is the location
1462;;; of the "lazy binder" hack.
1463;;;
1464;;; If symbol is defined in MODULE, and if the definition binds symbol
1465;;; to a variable, return that variable object.
1466;;;
1467;;; If the symbols is not found at first, but the module has a lazy binder,
1468;;; then try the binder.
1469;;;
1470;;; If the symbol is not found at all, return #f.
1471;;;
1472(define (module-local-variable m v)
1473 (caddr
1474 (list m v
1475 (let ((b (module-obarray-ref (module-obarray m) v)))
1476 (or (and (variable? b) b)
1477 (and (module-binder m)
1478 ((module-binder m) m v #f)))))))
1479
1480;; module-variable module symbol
1481;;
1482;; like module-local-variable, except search the uses in the
1483;; case V is not found in M.
1484;;
1485(define (module-variable m v)
1486 (module-search module-local-variable m v))
1487
1488
1489;;; {Mapping modules x symbols --> bindings}
1490;;;
1491;;; These are similar to the mapping to variables, except that the
1492;;; variable is dereferenced.
1493;;;
1494
1495;; module-symbol-binding module symbol opt-value
1496;;
1497;; return the binding of a variable specified by name within
1498;; a given module, signalling an error if the variable is unbound.
1499;; If the OPT-VALUE is passed, then instead of signalling an error,
1500;; return OPT-VALUE.
1501;;
1502(define (module-symbol-local-binding m v . opt-val)
1503 (let ((var (module-local-variable m v)))
1504 (if var
1505 (variable-ref var)
1506 (if (not (null? opt-val))
1507 (car opt-val)
1508 (error "Locally unbound variable." v)))))
1509
1510;; module-symbol-binding module symbol opt-value
1511;;
1512;; return the binding of a variable specified by name within
1513;; a given module, signalling an error if the variable is unbound.
1514;; If the OPT-VALUE is passed, then instead of signalling an error,
1515;; return OPT-VALUE.
1516;;
1517(define (module-symbol-binding m v . opt-val)
1518 (let ((var (module-variable m v)))
1519 (if var
1520 (variable-ref var)
1521 (if (not (null? opt-val))
1522 (car opt-val)
1523 (error "Unbound variable." v)))))
1524
1525
1526\f
1527;;; {Adding Variables to Modules}
1528;;;
1529;;;
1530
1531
1532;; module-make-local-var! module symbol
1533;;
1534;; ensure a variable for V in the local namespace of M.
1535;; If no variable was already there, then create a new and uninitialzied
1536;; variable.
1537;;
1538(define (module-make-local-var! m v)
1539 (or (let ((b (module-obarray-ref (module-obarray m) v)))
1540 (and (variable? b) b))
1541 (and (module-binder m)
1542 ((module-binder m) m v #t))
1543 (begin
1544 (let ((answer (make-undefined-variable v)))
1545 (module-obarray-set! (module-obarray m) v answer)
1546 answer))))
1547
1548;; module-add! module symbol var
1549;;
1550;; ensure a particular variable for V in the local namespace of M.
1551;;
1552(define (module-add! m v var)
1553 (if (not (variable? var))
1554 (error "Bad variable to module-add!" var))
1555 (module-obarray-set! (module-obarray m) v var))
1556
1557;; module-remove!
1558;;
1559;; make sure that a symbol is undefined in the local namespace of M.
1560;;
1561(define (module-remove! m v)
1562 (module-obarray-remove! (module-obarray m) v))
1563
1564(define (module-clear! m)
1565 (vector-fill! (module-obarray m) '()))
1566
1567;; MODULE-FOR-EACH -- exported
1568;;
1569;; Call PROC on each symbol in MODULE, with arguments of (SYMBOL VARIABLE).
1570;;
1571(define (module-for-each proc module)
1572 (let ((obarray (module-obarray module)))
1573 (do ((index 0 (+ index 1))
1574 (end (vector-length obarray)))
1575 ((= index end))
1576 (for-each
1577 (lambda (bucket)
1578 (proc (car bucket) (cdr bucket)))
1579 (vector-ref obarray index)))))
1580
1581
1582(define (module-map proc module)
1583 (let* ((obarray (module-obarray module))
1584 (end (vector-length obarray)))
1585
1586 (let loop ((i 0)
1587 (answer '()))
1588 (if (= i end)
1589 answer
1590 (loop (+ 1 i)
1591 (append!
1592 (map (lambda (bucket)
1593 (proc (car bucket) (cdr bucket)))
1594 (vector-ref obarray i))
1595 answer))))))
1596\f
1597
1598;;; {Low Level Bootstrapping}
1599;;;
1600
1601;; make-root-module
1602
1603:; A root module uses the symhash table (the system's privileged
1604;; obarray). Being inside a root module is like using SCM without
1605;; any module system.
1606;;
1607
1608
1609(define (root-module-thunk m s define?)
1610 (let ((bi (and (symbol-interned? #f s)
1611 (builtin-variable s))))
1612 (and bi
1613 (or define? (variable-bound? bi))
1614 (begin
1615 (module-add! m s bi)
1616 bi))))
1617
1618(define (make-root-module)
1619 (make-module 1019 #f root-module-thunk))
1620
1621
1622;; make-scm-module
1623
1624;; An scm module is a module into which the lazy binder copies
1625;; variable bindings from the system symhash table. The mapping is
1626;; one way only; newly introduced bindings in an scm module are not
1627;; copied back into the system symhash table (and can be used to override
1628;; bindings from the symhash table).
1629;;
1630
1631(define (make-scm-module)
1632 (make-module 1019 #f
1633 (lambda (m s define?)
1634 (let ((bi (and (symbol-interned? #f s)
1635 (builtin-variable s))))
1636 (and bi
1637 (variable-bound? bi)
1638 (begin
1639 (module-add! m s bi)
1640 bi))))))
1641
1642
1643
1644
1645;; the-module
1646;;
1647(define the-module #f)
1648
1649;; set-current-module module
1650;;
1651;; set the current module as viewed by the normalizer.
1652;;
1653(define (set-current-module m)
1654 (set! the-module m)
1655 (if m
1656 (set! *top-level-lookup-thunk* (module-eval-thunk the-module))
1657 (set! *top-level-lookup-thunk* #f)))
1658
1659
1660;; current-module
1661;;
1662;; return the current module as viewed by the normalizer.
1663;;
1664(define (current-module) the-module)
1665\f
1666;;; {Module-based Loading}
1667;;;
1668
1669(define (save-module-excursion thunk)
1670 (let ((inner-module (current-module))
1671 (outer-module #f))
1672 (dynamic-wind (lambda ()
1673 (set! outer-module (current-module))
1674 (set-current-module inner-module)
1675 (set! inner-module #f))
1676 thunk
1677 (lambda ()
1678 (set! inner-module (current-module))
1679 (set-current-module outer-module)
1680 (set! outer-module #f)))))
1681
1682(define basic-try-load-with-path try-load-with-path)
1683(define basic-try-load try-load)
1684(define basic-load-with-path load-with-path)
1685(define basic-load load)
1686
1687
1688(define (try-load-module-with-path . args)
1689 (save-module-excursion (lambda () (apply basic-try-load-with-path args))))
1690
1691(define (try-load-module . args)
1692 (save-module-excursion (lambda () (apply basic-try-load args))))
1693
1694(define (load-module-with-path . args)
1695 (save-module-excursion (lambda () (apply basic-load-with-path args))))
1696
1697(define (load-module . args)
1698 (save-module-excursion (lambda () (apply basic-load args))))
1699
1700
1701\f
1702
1703;; MODULE-REF -- exported
1704;;
1705;; Returns the value of a variable called NAME in MODULE or any of its
1706;; used modules. If there is no such variable, then if the optional third
1707;; argument DEFAULT is present, it is returned; otherwise an error is signaled.
1708;;
1709(define (module-ref module name . rest)
1710 (let ((variable (module-variable module name)))
1711 (if (and variable (variable-bound? variable))
1712 (variable-ref variable)
1713 (if (null? rest)
1714 (error "No variable named" name 'in module)
1715 (car rest) ; default value
1716 ))))
1717
1718;; MODULE-SET! -- exported
1719;;
1720;; Sets the variable called NAME in MODULE (or in a module that MODULE uses)
1721;; to VALUE; if there is no such variable, an error is signaled.
1722;;
1723(define (module-set! module name value)
1724 (let ((variable (module-variable module name)))
1725 (if variable
1726 (variable-set! variable value)
1727 (error "No variable named" name 'in module))))
1728
1729;; MODULE-DEFINE! -- exported
1730;;
1731;; Sets the variable called NAME in MODULE to VALUE; if there is no such
1732;; variable, it is added first.
1733;;
1734(define (module-define! module name value)
1735 (let ((variable (module-local-variable module name)))
1736 (if variable
1737 (variable-set! variable value)
1738 (module-add! module name (make-variable value name)))))
1739
1740;; MODULE-USE! module interface
1741;;
1742;; Add INTERFACE to the list of interfaces used by MODULE.
1743;;
1744(define (module-use! module interface)
1745 (set-module-uses! module
1746 (cons interface (delq! interface (module-uses module)))))
1747
1748\f
1749
1750
1751;;;;
1752;;; {Recursive Namespaces}
1753;;;
1754;;;
1755;;; A hierarchical namespace emerges if we consider some module to be
1756;;; root, and variables bound to modules as nested namespaces.
1757;;;
1758;;; The routines in this file manage variable names in hierarchical namespace.
1759;;; Each variable name is a list of elements, looked up in successively nested
1760;;; modules.
1761;;;
0dd5491c 1762;;; (nested-ref some-root-module '(foo bar baz))
0f2d19dd
JB
1763;;; => <value of a variable named baz in the module bound to bar in
1764;;; the module bound to foo in some-root-module>
1765;;;
1766;;;
1767;;; There are:
1768;;;
1769;;; ;; a-root is a module
1770;;; ;; name is a list of symbols
1771;;;
0dd5491c
MD
1772;;; nested-ref a-root name
1773;;; nested-set! a-root name val
1774;;; nested-define! a-root name val
1775;;; nested-remove! a-root name
0f2d19dd
JB
1776;;;
1777;;;
1778;;; (current-module) is a natural choice for a-root so for convenience there are
1779;;; also:
1780;;;
0dd5491c
MD
1781;;; local-ref name == nested-ref (current-module) name
1782;;; local-set! name val == nested-set! (current-module) name val
1783;;; local-define! name val == nested-define! (current-module) name val
1784;;; local-remove! name == nested-remove! (current-module) name
0f2d19dd
JB
1785;;;
1786
1787
0dd5491c 1788(define (nested-ref root names)
0f2d19dd
JB
1789 (let loop ((cur root)
1790 (elts names))
1791 (cond
1792 ((null? elts) cur)
1793 ((not (module? cur)) #f)
1794 (else (loop (module-ref cur (car elts) #f) (cdr elts))))))
1795
0dd5491c 1796(define (nested-set! root names val)
0f2d19dd
JB
1797 (let loop ((cur root)
1798 (elts names))
1799 (if (null? (cdr elts))
1800 (module-set! cur (car elts) val)
1801 (loop (module-ref cur (car elts)) (cdr elts)))))
1802
0dd5491c 1803(define (nested-define! root names val)
0f2d19dd
JB
1804 (let loop ((cur root)
1805 (elts names))
1806 (if (null? (cdr elts))
1807 (module-define! cur (car elts) val)
1808 (loop (module-ref cur (car elts)) (cdr elts)))))
1809
0dd5491c 1810(define (nested-remove! root names)
0f2d19dd
JB
1811 (let loop ((cur root)
1812 (elts names))
1813 (if (null? (cdr elts))
1814 (module-remove! cur (car elts))
1815 (loop (module-ref cur (car elts)) (cdr elts)))))
1816
0dd5491c
MD
1817(define (local-ref names) (nested-ref (current-module) names))
1818(define (local-set! names val) (nested-set! (current-module) names val))
1819(define (local-define names val) (nested-define! (current-module) names val))
1820(define (local-remove names) (nested-remove! (current-module) names))
0f2d19dd
JB
1821
1822
1823\f
1824
1825;;;;
1826;;; #/app
1827;;;
1828;;; The root of conventionally named objects not directly in the top level.
1829;;;
1830;;; #/app/modules
1831;;; #/app/modules/guile
1832;;;
1833;;; The directory of all modules and the standard root module.
1834;;;
1835
1836(define (module-public-interface m) (module-ref m '%module-public-interface #f))
1837(define (set-module-public-interface! m i) (module-define! m '%module-public-interface i))
1838(define the-root-module (make-root-module))
1839(define the-scm-module (make-scm-module))
1840(set-module-public-interface! the-root-module the-scm-module)
1841(set-module-name! the-root-module 'the-root-module)
1842(set-module-name! the-scm-module 'the-scm-module)
1843
1844(set-current-module the-root-module)
1845
1846(define app (make-module 31))
0dd5491c
MD
1847(local-define '(app modules) (make-module 31))
1848(local-define '(app modules guile) the-root-module)
0f2d19dd
JB
1849
1850;; (define-special-value '(app modules new-ws) (lambda () (make-scm-module)))
1851
1852(define (resolve-module name)
1853 (let ((full-name (append '(app modules) name)))
0dd5491c 1854 (let ((already (local-ref full-name)))
0f2d19dd
JB
1855 (or already
1856 (begin
1857 (try-module-autoload name)
1858 (make-modules-in (current-module) full-name))))))
1859
1860(define (beautify-user-module! module)
1861 (if (not (module-public-interface module))
1862 (let ((interface (make-module 31)))
1863 (set-module-name! interface (module-name module))
1864 (set-module-kind! interface 'interface)
1865 (set-module-public-interface! module interface)))
1866 (if (not (memq the-scm-module (module-uses module)))
1867 (set-module-uses! module (append (module-uses module) (list the-scm-module)))))
1868
1869(define (make-modules-in module name)
1870 (if (null? name)
1871 module
1872 (cond
1873 ((module-ref module (car name) #f) => (lambda (m) (make-modules-in m (cdr name))))
1874 (else (let ((m (make-module 31)))
1875 (set-module-kind! m 'directory)
1876 (set-module-name! m (car name))
1877 (module-define! module (car name) m)
1878 (make-modules-in m (cdr name)))))))
1879
1880(define (resolve-interface name)
1881 (let ((module (resolve-module name)))
1882 (and module (module-public-interface module))))
1883
1884
1885(define %autoloader-developer-mode #t)
1886
1887(define (process-define-module args)
1888 (let* ((module-id (car args))
1889 (module (resolve-module module-id))
1890 (kws (cdr args)))
1891 (beautify-user-module! module)
1892 (let loop ((kws kws))
1893 (and (not (null? kws))
1894 (case (car kws)
1895 ((:use-module)
1896 (if (not (pair? (cdr kws)))
1897 (error "unrecognized defmodule argument" kws))
1898 (let* ((used-name (cadr kws))
1899 (used-module (resolve-module used-name)))
1900 (if (not (module-ref used-module '%module-public-interface #f))
1901 (begin
1902 ((if %autoloader-developer-mode warn error) "no code for module" used-module)
1903 (beautify-user-module! used-module)))
1904 (let ((interface (module-ref used-module '%module-public-interface #f)))
1905 (if (not interface)
1906 (error "missing interface for use-module" used-module))
1907 (set-module-uses! module
1908 (append! (delq! interface (module-uses module))
1909 (list interface)))))
1910 (loop (cddr kws)))
1911
1912 (else (error "unrecognized defmodule argument" kws)))))
1913 module))
1914\f
1915
1916(define autoloads-in-progress '())
1917
1918(define (try-module-autoload module-name)
1919
1920 (define (sfx name) (string-append name (scheme-file-suffix)))
1921 (let* ((reverse-name (reverse module-name))
1922 (name (car reverse-name))
1923 (dir-hint-module-name (reverse (cdr reverse-name)))
1924 (dir-hint (apply symbol-append (map (lambda (elt) (symbol-append elt "/")) dir-hint-module-name))))
1925 (resolve-module dir-hint-module-name)
1926 (and (not (autoload-done-or-in-progress? dir-hint name))
1927 (let ((didit #f))
1928 (dynamic-wind
1929 (lambda () (autoload-in-progress! dir-hint name))
1930 (lambda ()
1931 (let loop ((dirs %load-path))
1932 (and (not (null? dirs))
1933 (or
1934 (let ((d (car dirs))
1935 (trys (list
1936 dir-hint
1937 (sfx dir-hint)
1938 (in-vicinity dir-hint name)
1939 (in-vicinity dir-hint (sfx name)))))
1940 (and (or-map (lambda (f)
1941 (let ((full (in-vicinity d f)))
1942 full
1943 (and (not (file-is-directory? full))
1944 (file-exists? full)
1945 (begin
1946 (save-module-excursion
1947 (lambda ()
1948 (list f d)
1949 (load-with-path f (list d))))
1950 #t))))
1951 trys)
1952 (begin
1953 (set! didit #t)
1954 #t)))
1955 (loop (cdr dirs))))))
1956 (lambda () (set-autoloaded! dir-hint name didit)))
1957 didit))))
1958
1959(define autoloads-done '((guile . guile)))
1960
1961(define (autoload-done-or-in-progress? p m)
1962 (let ((n (cons p m)))
1963 (->bool (or (member n autoloads-done)
1964 (member n autoloads-in-progress)))))
1965
1966(define (autoload-done! p m)
1967 (let ((n (cons p m)))
1968 (set! autoloads-in-progress
1969 (delete! n autoloads-in-progress))
1970 (or (member n autoloads-done)
1971 (set! autoloads-done (cons n autoloads-done)))))
1972
1973(define (autoload-in-progress! p m)
1974 (let ((n (cons p m)))
1975 (set! autoloads-done
1976 (delete! n autoloads-done))
1977 (set! autoloads-in-progress (cons n autoloads-in-progress))))
1978
1979(define (set-autoloaded! p m done?)
1980 (if done?
1981 (autoload-done! p m)
1982 (let ((n (cons p m)))
1983 (set! autoloads-done (delete! n autoloads-done))
1984 (set! autoloads-in-progress (delete! n autoloads-in-progress)))))
1985
1986
1987
1988
1989\f
1990;;; {Macros}
1991;;;
1992
9591db87
MD
1993(define macro-table (make-weak-key-hash-table 523))
1994(define xformer-table (make-weak-key-hash-table 523))
0f2d19dd
JB
1995
1996(define (defmacro? m) (hashq-ref macro-table m))
1997(define (assert-defmacro?! m) (hashq-set! macro-table m #t))
1998(define (defmacro-transformer m) (hashq-ref xformer-table m))
1999(define (set-defmacro-transformer! m t) (hashq-set! xformer-table m t))
2000
2001(define defmacro:transformer
2002 (lambda (f)
2003 (let* ((xform (lambda (exp env)
2004 (copy-tree (apply f (cdr exp)))))
2005 (a (procedure->memoizing-macro xform)))
2006 (assert-defmacro?! a)
2007 (set-defmacro-transformer! a f)
2008 a)))
2009
2010
2011(define defmacro
2012 (let ((defmacro-transformer
2013 (lambda (name parms . body)
2014 (let ((transformer `(lambda ,parms ,@body)))
2015 `(define ,name
2016 (,(lambda (transformer)
2017 (defmacro:transformer transformer))
2018 ,transformer))))))
2019 (defmacro:transformer defmacro-transformer)))
2020
2021(define defmacro:syntax-transformer
2022 (lambda (f)
2023 (procedure->syntax
2024 (lambda (exp env)
2025 (copy-tree (apply f (cdr exp)))))))
2026
2027(define (macroexpand-1 e)
2028 (cond
2029 ((pair? e) (let* ((a (car e))
2030 (val (and (symbol? a) (eval `(defined? ,a)) (eval a))))
2031 (if (defmacro? val)
2032 (apply (defmacro-transformer val) (cdr e))
2033 e)))
2034 (#t e)))
2035
2036(define (macroexpand e)
2037 (cond
2038 ((pair? e) (let* ((a (car e))
2039 (val (and (symbol? a) (eval `(defined? ,a)) (eval a))))
2040 (if (defmacro? val)
2041 (macroexpand (apply (defmacro-transformer val) (cdr e)))
2042 e)))
2043 (#t e)))
2044
2045(define gentemp
2046 (let ((*gensym-counter* -1))
2047 (lambda ()
2048 (set! *gensym-counter* (+ *gensym-counter* 1))
2049 (string->symbol
2050 (string-append "scm:G" (number->string *gensym-counter*))))))
2051
2052
2053\f
2054
2055;;; {Running Repls}
2056;;;
2057
2058(define (repl read evaler print)
2059 (let loop ((source (read (current-input-port) #t read-sharp)))
2060 (print (evaler source))
2061 (loop (read (current-input-port) #t read-sharp))))
2062
2063;; A provisional repl that acts like the SCM repl:
2064;;
2065(define scm-repl-silent #f)
2066(define (assert-repl-silence v) (set! scm-repl-silent v))
2067
2068(define scm-repl-verbose #t)
2069(define (assert-repl-verbosity v) (set! scm-repl-verbose v))
2070
2071(define scm-repl-prompt #t)
2072(define (assert-repl-prompt v) (set! scm-repl-prompt v))
2073
2074(define the-prompt-string "guile> ")
2075
2076(define (error-catching-loop thunk)
2077 (define (loop first)
2078 (let ((next
2079 (catch #t
2080 (lambda ()
2081 (dynamic-wind
2082 (lambda () (unmask-signals))
2083 (lambda ()
2084 (first)
2085
2086 ;; This line is needed because mark doesn't do closures quite right.
2087 ;; Unreferenced locals should be collected.
2088 ;;
2089 (set! first #f)
2090 (let loop ((v (thunk)))
2091 (loop (thunk)))
2092 #f)
2093 (lambda () (mask-signals))))
2094
2095 (lambda (key . args)
2096 (case key
2097 ((quit) (force-output)
2098 (pk 'quit args)
2099 #f)
2100
2101 ((abort) ;; This is one of the closures that require (set! first #f)
2102 ;; above
2103 ;;
2104 (lambda ()
2105 (force-output)
2106 (display "ABORT: " (current-error-port))
2107 (write args (current-error-port))
2108 (newline (current-error-port))))
2109
2110 (else ;; This is the other cons-leak closure...
2111 (lambda ()
2112 (apply %%bad-throw key args))))))))
2113 (and next (loop next))))
2114 (loop (lambda () #t)))
2115
2116(define (quit . args)
2117 (apply throw 'quit args))
2118
2119(define (error-catching-repl r e p)
2120 (error-catching-loop (lambda () (p (e (r))))))
2121
2122(define (gc-run-time)
2123 (cdr (assq 'gc-time-taken (gc-stats))))
2124
2125(define (scm-style-repl)
2126 (letrec (
2127 (start-gc-rt #f)
2128 (start-rt #f)
2129 (repl-report-reset (lambda () #f))
2130 (repl-report-start-timing (lambda ()
2131 (set! start-gc-rt (gc-run-time))
2132 (set! start-rt (get-internal-run-time))))
2133 (repl-report (lambda ()
2134 (display ";;; ")
2135 (display (inexact->exact
2136 (* 1000 (/ (- (get-internal-run-time) start-rt)
2137 internal-time-units-per-second))))
2138 (display " msec (")
2139 (display (inexact->exact
2140 (* 1000 (/ (- (gc-run-time) start-gc-rt)
2141 internal-time-units-per-second))))
2142 (display " msec in gc)\n")))
2143 (-read (lambda ()
2144 (if scm-repl-prompt
2145 (begin
2146 (display the-prompt-string)
2147 (force-output)
2148 (repl-report-reset)))
2149 (let ((val (read (current-input-port) #t read-sharp)))
2150 (if (eof-object? val)
2151 (begin
2152 (if scm-repl-verbose
2153 (begin
2154 (newline)
2155 (display ";;; EOF -- quitting")
2156 (newline)))
2157 (quit 0)))
2158 val)))
2159
2160 (-eval (lambda (sourc)
2161 (repl-report-start-timing)
2162 (eval sourc)))
2163
2164 (-print (lambda (result)
2165 (if (not scm-repl-silent)
2166 (begin
2167 (print result)
2168 (newline)
2169 (if scm-repl-verbose
2170 (repl-report))
2171 (force-output)))))
2172
2173 (-quit (lambda ()
2174 (if scm-repl-verbose
2175 (begin
2176 (display ";;; QUIT executed, repl exitting")
2177 (newline)
2178 (repl-report)))
2179 #t))
2180
2181 (-abort (lambda ()
2182 (if scm-repl-verbose
2183 (begin
2184 (display ";;; ABORT executed.")
2185 (newline)
2186 (repl-report)))
2187 (repl -read -eval -print))))
2188
2189 (error-catching-repl -read
2190 -eval
2191 -print)))
2192
2193(define (stand-alone-repl)
2194 (let ((oport (current-input-port)))
2195 (set-current-input-port *stdin*)
2196 (scm-style-repl)
2197 (set-current-input-port oport)))
2198
2199
2200\f
2201
2202
2203(define (reverse-iota n) (if (> n 0) (cons (1- n) (reverse-iota (1- n))) '()))
2204(define (iota n) (list-reverse! (reverse-iota n)))
2205
2206\f
2207;;; {While}
2208;;;
2209;;; with `continue' and `break'.
2210;;;
2211
2212(defmacro while (cond . body)
2213 `(letrec ((continue (lambda () (or (not ,cond) (begin (begin ,@ body) (continue)))))
2214 (break (lambda val (apply throw 'break val))))
2215 (catch 'break
2216 (lambda () (continue))
2217 (lambda v (cadr v)))))
2218
2219
2220\f
2221
2222;;; {Macros}
2223;;;
2224
2225;; actually....hobbit might be able to hack these with a little
2226;; coaxing
2227;;
2228
2229(defmacro define-macro (first . rest)
2230 (let ((name (if (symbol? first) first (car first)))
2231 (transformer
2232 (if (symbol? first)
2233 (car rest)
2234 `(lambda ,(cdr first) ,@rest))))
2235 `(define ,name (defmacro:transformer ,transformer))))
2236
2237
2238(defmacro define-syntax-macro (first . rest)
2239 (let ((name (if (symbol? first) first (car first)))
2240 (transformer
2241 (if (symbol? first)
2242 (car rest)
2243 `(lambda ,(cdr first) ,@rest))))
2244 `(define ,name (defmacro:syntax-transformer ,transformer))))
2245\f
2246;;; {Module System Macros}
2247;;;
2248
2249(defmacro define-module args
2250 `(let* ((process-define-module process-define-module)
2251 (set-current-module set-current-module)
2252 (module (process-define-module ',args)))
2253 (set-current-module module)
2254 module))
2255
2256(define define-private define)
2257
2258(defmacro define-public args
2259 (define (syntax)
2260 (error "bad syntax" (list 'define-public args)))
2261 (define (defined-name n)
2262 (cond
2263 ((symbol? n) n)
2264 ((pair? n) (defined-name (car n)))
2265 (else (syntax))))
2266 (cond
2267 ((null? args) (syntax))
2268
2269 (#t (let ((name (defined-name (car args))))
2270 `(begin
2271 (let ((public-i (module-public-interface (current-module))))
2272 ;; Make sure there is a local variable:
2273 ;;
2274 (module-define! (current-module)
2275 ',name
2276 (module-ref (current-module) ',name #f))
2277
2278 ;; Make sure that local is exported:
2279 ;;
2280 (module-add! public-i ',name (module-variable (current-module) ',name)))
2281
2282 ;; Now (re)define the var normally.
2283 ;;
2284 (define-private ,@ args))))))
2285
2286
2287
2288(defmacro defmacro-public args
2289 (define (syntax)
2290 (error "bad syntax" (list 'defmacro-public args)))
2291 (define (defined-name n)
2292 (cond
2293 ((symbol? n) n)
2294 (else (syntax))))
2295 (cond
2296 ((null? args) (syntax))
2297
2298 (#t (let ((name (defined-name (car args))))
2299 `(begin
2300 (let ((public-i (module-public-interface (current-module))))
2301 ;; Make sure there is a local variable:
2302 ;;
2303 (module-define! (current-module)
2304 ',name
2305 (module-ref (current-module) ',name #f))
2306
2307 ;; Make sure that local is exported:
2308 ;;
2309 (module-add! public-i ',name (module-variable (current-module) ',name)))
2310
2311 ;; Now (re)define the var normally.
2312 ;;
2313 (defmacro ,@ args))))))
2314
2315
2316
2317
2318(define try-load-with-path try-load-module-with-path)
2319(define try-load try-load-module)
2320(define load-with-path load-module-with-path)
2321(define load load-module)
2322
2323
2324\f
2325
2326;; (define in-ch (get-standard-channel TCL_STDIN))
2327;; (define out-ch (get-standard-channel TCL_STDOUT))
2328;; (define err-ch (get-standard-channel TCL_STDERR))
2329;;
2330;; (define inp (%make-channel-port in-ch "r"))
2331;; (define outp (%make-channel-port out-ch "w"))
2332;; (define errp (%make-channel-port err-ch "w"))
2333;;
2334;; (define %system-char-ready? char-ready?)
2335;;
2336;; (define (char-ready? p)
2337;; (if (not (channel-port? p))
2338;; (%system-char-ready? p)
2339;; (let* ((channel (%channel-port-channel p))
2340;; (old-blocking (channel-option-ref channel :blocking)))
2341;; (dynamic-wind
2342;; (lambda () (set-channel-option the-root-tcl-interpreter channel :blocking "0"))
2343;; (lambda () (not (eof-object? (peek-char p))))
2344;; (lambda () (set-channel-option the-root-tcl-interpreter channel :blocking old-blocking))))))
2345;;
2346;; (define (top-repl)
2347;; (with-input-from-port inp
2348;; (lambda ()
2349;; (with-output-to-port outp
2350;; (lambda ()
2351;; (with-error-to-port errp
2352;; (lambda ()
2353;; (scm-style-repl))))))))
2354;;
2355;; (set-current-input-port inp)
2356;; (set-current-output-port outp)
2357;; (set-current-error-port errp)
2358
2359(define (top-repl) (scm-style-repl))
2360
02b754d3
GH
2361(defmacro false-if-exception (expr)
2362 `(catch #t (lambda () ,expr)
2363 (lambda args #f)))
2364
0f2d19dd
JB
2365\f
2366(define-module (ice-9 calling))
2367
2368;;;;
2369;;; {Calling Conventions}
2370;;;
2371;;; This file contains a number of macros that support
2372;;; common calling conventions.
2373
2374;;;
2375;;; with-excursion-function <vars> proc
2376;;; <vars> is an unevaluated list of names that are bound in the caller.
2377;;; proc is a procedure, called:
2378;;; (proc excursion)
2379;;;
2380;;; excursion is a procedure isolates all changes to <vars>
2381;;; in the dynamic scope of the call to proc. In other words,
2382;;; the values of <vars> are saved when proc is entered, and when
2383;;; proc returns, those values are restored. Values are also restored
2384;;; entering and leaving the call to proc non-locally, such as using
2385;;; call-with-current-continuation, error, or throw.
2386;;;
2387(defmacro-public with-excursion-function (vars proc)
2388 `(,proc ,(excursion-function-syntax vars)))
2389
2390
2391
2392;;; with-getter-and-setter <vars> proc
2393;;; <vars> is an unevaluated list of names that are bound in the caller.
2394;;; proc is a procedure, called:
2395;;; (proc getter setter)
2396;;;
2397;;; getter and setter are procedures used to access
2398;;; or modify <vars>.
2399;;;
2400;;; setter, called with keywords arguments, modifies the named
2401;;; values. If "foo" and "bar" are among <vars>, then:
2402;;;
2403;;; (setter :foo 1 :bar 2)
2404;;; == (set! foo 1 bar 2)
2405;;;
2406;;; getter, called with just keywords, returns
2407;;; a list of the corresponding values. For example,
2408;;; if "foo" and "bar" are among the <vars>, then
2409;;;
2410;;; (getter :foo :bar)
2411;;; => (<value-of-foo> <value-of-bar>)
2412;;;
2413;;; getter, called with no arguments, returns a list of all accepted
2414;;; keywords and the corresponding values. If "foo" and "bar" are
2415;;; the *only* <vars>, then:
2416;;;
2417;;; (getter)
2418;;; => (:foo <value-of-bar> :bar <value-of-foo>)
2419;;;
2420;;; The unusual calling sequence of a getter supports too handy
2421;;; idioms:
2422;;;
2423;;; (apply setter (getter)) ;; save and restore
2424;;;
2425;;; (apply-to-args (getter :foo :bar) ;; fetch and bind
2426;;; (lambda (foo bar) ....))
2427;;;
2428;;; ;; [ "apply-to-args" is just like two-argument "apply" except that it
2429;;; ;; takes its arguments in a different order.
2430;;;
2431;;;
2432(defmacro-public with-getter-and-setter (vars proc)
2433 `(,proc ,@ (getter-and-setter-syntax vars)))
2434
2435;;; with-getter vars proc
2436;;; A short-hand for a call to with-getter-and-setter.
2437;;; The procedure is called:
2438;;; (proc getter)
2439;;;
2440(defmacro-public with-getter (vars proc)
2441 `(,proc ,(car (getter-and-setter-syntax vars))))
2442
2443
2444;;; with-delegating-getter-and-setter <vars> get-delegate set-delegate proc
2445;;; Compose getters and setters.
2446;;;
2447;;; <vars> is an unevaluated list of names that are bound in the caller.
2448;;;
2449;;; get-delegate is called by the new getter to extend the set of
2450;;; gettable variables beyond just <vars>
2451;;; set-delegate is called by the new setter to extend the set of
2452;;; gettable variables beyond just <vars>
2453;;;
2454;;; proc is a procedure that is called
2455;;; (proc getter setter)
2456;;;
2457(defmacro-public with-delegating-getter-and-setter (vars get-delegate set-delegate proc)
2458 `(,proc ,@ (delegating-getter-and-setter-syntax vars get-delegate set-delegate)))
2459
2460
2461;;; with-delegating-getter-and-setter <vars> get-delegate set-delegate proc
2462;;; <vars> is an unevaluated list of names that are bound in the caller.
2463;;; proc is called:
2464;;;
2465;;; (proc excursion getter setter)
2466;;;
2467;;; See also:
2468;;; with-getter-and-setter
2469;;; with-excursion-function
2470;;;
2471(defmacro-public with-excursion-getter-and-setter (vars proc)
2472 `(,proc ,(excursion-function-syntax vars)
2473 ,@ (getter-and-setter-syntax vars)))
2474
2475
2476(define (excursion-function-syntax vars)
2477 (let ((saved-value-names (map gensym vars))
2478 (tmp-var-name (gensym 'temp))
2479 (swap-fn-name (gensym 'swap))
2480 (thunk-name (gensym 'thunk)))
2481 `(lambda (,thunk-name)
2482 (letrec ((,tmp-var-name #f)
2483 (,swap-fn-name
2484 (lambda () ,@ (map (lambda (n sn) `(set! ,tmp-var-name ,n ,n ,sn ,sn ,tmp-var-name))
2485 vars saved-value-names)))
2486 ,@ (map (lambda (sn n) `(,sn ,n)) saved-value-names vars))
2487 (dynamic-wind
2488 ,swap-fn-name
2489 ,thunk-name
2490 ,swap-fn-name)))))
2491
2492
2493(define (getter-and-setter-syntax vars)
2494 (let ((args-name (gensym 'args))
2495 (an-arg-name (gensym 'an-arg))
2496 (new-val-name (gensym 'new-value))
2497 (loop-name (gensym 'loop))
2498 (kws (map symbol->keyword vars)))
2499 (list `(lambda ,args-name
2500 (let ,loop-name ((,args-name ,args-name))
2501 (if (null? ,args-name)
2502 ,(if (null? kws)
2503 ''()
2504 `(let ((all-vals (,loop-name ',kws)))
2505 (let ,loop-name ((vals all-vals)
2506 (kws ',kws))
2507 (if (null? vals)
2508 '()
2509 `(,(car kws) ,(car vals) ,@(,loop-name (cdr vals) (cdr kws)))))))
2510 (map (lambda (,an-arg-name)
2511 (case ,an-arg-name
2512 ,@ (append
2513 (map (lambda (kw v) `((,kw) ,v)) kws vars)
2514 `((else (throw 'bad-get-option ,an-arg-name))))))
2515 ,args-name))))
2516
2517 `(lambda ,args-name
2518 (let ,loop-name ((,args-name ,args-name))
2519 (or (null? ,args-name)
2520 (null? (cdr ,args-name))
2521 (let ((,an-arg-name (car ,args-name))
2522 (,new-val-name (cadr ,args-name)))
2523 (case ,an-arg-name
2524 ,@ (append
2525 (map (lambda (kw v) `((,kw) (set! ,v ,new-val-name))) kws vars)
2526 `((else (throw 'bad-set-option ,an-arg-name)))))
2527 (,loop-name (cddr ,args-name)))))))))
2528
2529(define (delegating-getter-and-setter-syntax vars get-delegate set-delegate)
2530 (let ((args-name (gensym 'args))
2531 (an-arg-name (gensym 'an-arg))
2532 (new-val-name (gensym 'new-value))
2533 (loop-name (gensym 'loop))
2534 (kws (map symbol->keyword vars)))
2535 (list `(lambda ,args-name
2536 (let ,loop-name ((,args-name ,args-name))
2537 (if (null? ,args-name)
2538 (append!
2539 ,(if (null? kws)
2540 ''()
2541 `(let ((all-vals (,loop-name ',kws)))
2542 (let ,loop-name ((vals all-vals)
2543 (kws ',kws))
2544 (if (null? vals)
2545 '()
2546 `(,(car kws) ,(car vals) ,@(,loop-name (cdr vals) (cdr kws)))))))
2547 (,get-delegate))
2548 (map (lambda (,an-arg-name)
2549 (case ,an-arg-name
2550 ,@ (append
2551 (map (lambda (kw v) `((,kw) ,v)) kws vars)
2552 `((else (car (,get-delegate ,an-arg-name)))))))
2553 ,args-name))))
2554
2555 `(lambda ,args-name
2556 (let ,loop-name ((,args-name ,args-name))
2557 (or (null? ,args-name)
2558 (null? (cdr ,args-name))
2559 (let ((,an-arg-name (car ,args-name))
2560 (,new-val-name (cadr ,args-name)))
2561 (case ,an-arg-name
2562 ,@ (append
2563 (map (lambda (kw v) `((,kw) (set! ,v ,new-val-name))) kws vars)
2564 `((else (,set-delegate ,an-arg-name ,new-val-name)))))
2565 (,loop-name (cddr ,args-name)))))))))
2566
2567
2568
2569
2570;;; with-configuration-getter-and-setter <vars-etc> proc
2571;;;
2572;;; Create a getter and setter that can trigger arbitrary computation.
2573;;;
2574;;; <vars-etc> is a list of variable specifiers, explained below.
2575;;; proc is called:
2576;;;
2577;;; (proc getter setter)
2578;;;
2579;;; Each element of the <vars-etc> list is of the form:
2580;;;
2581;;; (<var> getter-hook setter-hook)
2582;;;
2583;;; Both hook elements are evaluated; the variable name is not.
2584;;; Either hook may be #f or procedure.
2585;;;
2586;;; A getter hook is a thunk that returns a value for the corresponding
2587;;; variable. If omitted (#f is passed), the binding of <var> is
2588;;; returned.
2589;;;
2590;;; A setter hook is a procedure of one argument that accepts a new value
2591;;; for the corresponding variable. If omitted, the binding of <var>
2592;;; is simply set using set!.
2593;;;
2594(defmacro-public with-configuration-getter-and-setter (vars-etc proc)
2595 `((lambda (simpler-get simpler-set body-proc)
2596 (with-delegating-getter-and-setter ()
2597 simpler-get simpler-set body-proc))
2598
2599 (lambda (kw)
2600 (case kw
2601 ,@(map (lambda (v) `((,(symbol->keyword (car v)))
2602 ,(cond
2603 ((cadr v) => list)
2604 (else `(list ,(car v))))))
2605 vars-etc)))
2606
2607 (lambda (kw new-val)
2608 (case kw
2609 ,@(map (lambda (v) `((,(symbol->keyword (car v)))
2610 ,(cond
2611 ((caddr v) => (lambda (proc) `(,proc new-val)))
2612 (else `(set! ,(car v) new-val)))))
2613 vars-etc)))
2614
2615 ,proc))
2616
2617(defmacro-public with-delegating-configuration-getter-and-setter (vars-etc delegate-get delegate-set proc)
2618 `((lambda (simpler-get simpler-set body-proc)
2619 (with-delegating-getter-and-setter ()
2620 simpler-get simpler-set body-proc))
2621
2622 (lambda (kw)
2623 (case kw
2624 ,@(append! (map (lambda (v) `((,(symbol->keyword (car v)))
2625 ,(cond
2626 ((cadr v) => list)
2627 (else `(list ,(car v))))))
2628 vars-etc)
2629 `((else (,delegate-get kw))))))
2630
2631 (lambda (kw new-val)
2632 (case kw
2633 ,@(append! (map (lambda (v) `((,(symbol->keyword (car v)))
2634 ,(cond
2635 ((caddr v) => (lambda (proc) `(,proc new-val)))
2636 (else `(set! ,(car v) new-val)))))
2637 vars-etc)
2638 `((else (,delegate-set kw new-val))))))
2639
2640 ,proc))
2641
2642
2643;;; let-configuration-getter-and-setter <vars-etc> proc
2644;;;
2645;;; This procedure is like with-configuration-getter-and-setter (q.v.)
2646;;; except that each element of <vars-etc> is:
2647;;;
2648;;; (<var> initial-value getter-hook setter-hook)
2649;;;
2650;;; Unlike with-configuration-getter-and-setter, let-configuration-getter-and-setter
2651;;; introduces bindings for the variables named in <vars-etc>.
2652;;; It is short-hand for:
2653;;;
2654;;; (let ((<var1> initial-value-1)
2655;;; (<var2> initial-value-2)
2656;;; ...)
2657;;; (with-configuration-getter-and-setter ((<var1> v1-get v1-set) ...) proc))
2658;;;
2659(defmacro-public let-with-configuration-getter-and-setter (vars-etc proc)
2660 `(let ,(map (lambda (v) `(,(car v) ,(cadr v))) vars-etc)
2661 (with-configuration-getter-and-setter ,(map (lambda (v) `(,(car v) ,(caddr v) ,(cadddr v))) vars-etc)
2662 ,proc)))
2663
2664
2665
2666\f
2667(define-module (ice-9 common-list))
2668
2669;;"comlist.scm" Implementation of COMMON LISP list functions for Scheme
2670; Copyright (C) 1991, 1993, 1995 Aubrey Jaffer.
2671;
2672;Permission to copy this software, to redistribute it, and to use it
2673;for any purpose is granted, subject to the following restrictions and
2674;understandings.
2675;
2676;1. Any copy made of this software must include this copyright notice
2677;in full.
2678;
2679;2. I have made no warrantee or representation that the operation of
2680;this software will be error-free, and I am under no obligation to
2681;provide any services, by way of maintenance, update, or otherwise.
2682;
2683;3. In conjunction with products arising from the use of this
2684;material, there shall be no use of my name in any advertising,
2685;promotional, or sales literature without prior written consent in
2686;each case.
2687
2688\f
2689
2690
2691;;;From: hugh@ear.mit.edu (Hugh Secker-Walker)
2692(define-public (make-list k . init)
2693 (set! init (if (pair? init) (car init)))
2694 (do ((k k (+ -1 k))
2695 (result '() (cons init result)))
2696 ((<= k 0) result)))
2697
2698(define-public (adjoin e l) (if (memq e l) l (cons e l)))
2699
2700(define-public (union l1 l2)
2701 (cond ((null? l1) l2)
2702 ((null? l2) l1)
2703 (else (union (cdr l1) (adjoin (car l1) l2)))))
2704
2705(define-public (intersection l1 l2)
2706 (cond ((null? l1) l1)
2707 ((null? l2) l2)
2708 ((memv (car l1) l2) (cons (car l1) (intersection (cdr l1) l2)))
2709 (else (intersection (cdr l1) l2))))
2710
2711(define-public (set-difference l1 l2)
2712 (cond ((null? l1) l1)
2713 ((memv (car l1) l2) (set-difference (cdr l1) l2))
2714 (else (cons (car l1) (set-difference (cdr l1) l2)))))
2715
2716(define-public (reduce-init p init l)
2717 (if (null? l)
2718 init
2719 (reduce-init p (p init (car l)) (cdr l))))
2720
2721(define-public (reduce p l)
2722 (cond ((null? l) l)
2723 ((null? (cdr l)) (car l))
2724 (else (reduce-init p (car l) (cdr l)))))
2725
2726(define-public (some pred l . rest)
2727 (cond ((null? rest)
2728 (let mapf ((l l))
2729 (and (not (null? l))
2730 (or (pred (car l)) (mapf (cdr l))))))
2731 (else (let mapf ((l l) (rest rest))
2732 (and (not (null? l))
2733 (or (apply pred (car l) (map car rest))
2734 (mapf (cdr l) (map cdr rest))))))))
2735
2736(define-public (every pred l . rest)
2737 (cond ((null? rest)
2738 (let mapf ((l l))
2739 (or (null? l)
2740 (and (pred (car l)) (mapf (cdr l))))))
2741 (else (let mapf ((l l) (rest rest))
2742 (or (null? l)
2743 (and (apply pred (car l) (map car rest))
2744 (mapf (cdr l) (map cdr rest))))))))
2745
2746(define-public (notany pred . ls) (not (apply some pred ls)))
2747
2748(define-public (notevery pred . ls) (not (apply every pred ls)))
2749
2750(define-public (find-if t l)
2751 (cond ((null? l) #f)
2752 ((t (car l)) (car l))
2753 (else (find-if t (cdr l)))))
2754
2755(define-public (member-if t l)
2756 (cond ((null? l) #f)
2757 ((t (car l)) l)
2758 (else (member-if t (cdr l)))))
2759
2760(define-public (remove-if p l)
2761 (cond ((null? l) '())
2762 ((p (car l)) (remove-if p (cdr l)))
2763 (else (cons (car l) (remove-if p (cdr l))))))
2764
2765(define-public (delete-if! pred list)
2766 (let delete-if ((list list))
2767 (cond ((null? list) '())
2768 ((pred (car list)) (delete-if (cdr list)))
2769 (else
2770 (set-cdr! list (delete-if (cdr list)))
2771 list))))
2772
2773(define-public (delete-if-not! pred list)
2774 (let delete-if ((list list))
2775 (cond ((null? list) '())
2776 ((not (pred (car list))) (delete-if (cdr list)))
2777 (else
2778 (set-cdr! list (delete-if (cdr list)))
2779 list))))
2780
2781(define-public (butlast lst n)
2782 (letrec ((l (- (length lst) n))
2783 (bl (lambda (lst n)
2784 (cond ((null? lst) lst)
2785 ((positive? n)
2786 (cons (car lst) (bl (cdr lst) (+ -1 n))))
2787 (else '())))))
2788 (bl lst (if (negative? n)
2789 (slib:error "negative argument to butlast" n)
2790 l))))
2791
2792(define-public (and? . args)
2793 (cond ((null? args) #t)
2794 ((car args) (apply and? (cdr args)))
2795 (else #f)))
2796
2797(define-public (or? . args)
2798 (cond ((null? args) #f)
2799 ((car args) #t)
2800 (else (apply or? (cdr args)))))
2801
2802(define-public (has-duplicates? lst)
2803 (cond ((null? lst) #f)
2804 ((member (car lst) (cdr lst)) #t)
2805 (else (has-duplicates? (cdr lst)))))
2806
2807(define-public (list* x . y)
2808 (define (list*1 x)
2809 (if (null? (cdr x))
2810 (car x)
2811 (cons (car x) (list*1 (cdr x)))))
2812 (if (null? y)
2813 x
2814 (cons x (list*1 y))))
2815
2816;; pick p l
2817;; Apply P to each element of L, returning a list of elts
2818;; for which P returns a non-#f value.
2819;;
2820(define-public (pick p l)
2821 (let loop ((s '())
2822 (l l))
2823 (cond
2824 ((null? l) s)
2825 ((p (car l)) (loop (cons (car l) s) (cdr l)))
2826 (else (loop s (cdr l))))))
2827
2828;; pick p l
2829;; Apply P to each element of L, returning a list of the
2830;; non-#f return values of P.
2831;;
2832(define-public (pick-mappings p l)
2833 (let loop ((s '())
2834 (l l))
2835 (cond
2836 ((null? l) s)
2837 ((p (car l)) => (lambda (mapping) (loop (cons mapping s) (cdr l))))
2838 (else (loop s (cdr l))))))
2839
2840(define-public (uniq l)
2841 (if (null? l)
2842 '()
2843 (let ((u (uniq (cdr l))))
2844 (if (memq (car l) u)
2845 u
2846 (cons (car l) u)))))
2847
2848\f
2849(define-module (ice-9 ls)
2850 :use-module (ice-9 common-list))
2851
2852\f
2853
2854;;;;
2855;;; local-definitions-in root name
2856;;; Returns a list of names defined locally in the named subdirectory of root.
2857;;; definitions-in root name
2858;;; Returns a list of all names defined in the named subdirectory of root.
2859;;; The list includes alll locally defined names as well as all names inherited
2860;;; from a member of a use-list.
2861;;;
2862;;; A convenient interface for examining the nature of things:
2863;;;
2864;;; ls . various-names
2865;;;
2866;;; With just one argument, interpret that argument as the name of a subdirectory
2867;;; of the current module and return a list of names defined there.
2868;;;
2869;;; With more than one argument, still compute subdirectory lists, but
2870;;; return a list:
2871;;; ((<subdir-name> . <names-defined-there>)
2872;;; (<subdir-name> . <names-defined-there>)
2873;;; ...)
2874;;;
2875
2876(define-public (local-definitions-in root names)
0dd5491c 2877 (let ((m (nested-ref root names))
0f2d19dd
JB
2878 (answer '()))
2879 (if (not (module? m))
2880 (set! answer m)
2881 (module-for-each (lambda (k v) (set! answer (cons k answer))) m))
2882 answer))
2883
2884(define-public (definitions-in root names)
0dd5491c 2885 (let ((m (nested-ref root names)))
0f2d19dd
JB
2886 (if (not (module? m))
2887 m
2888 (reduce union
2889 (cons (local-definitions-in m '())
2890 (map (lambda (m2) (definitions-in m2 '())) (module-uses m)))))))
2891
2892(define-public (ls . various-refs)
2893 (and various-refs
2894 (if (cdr various-refs)
2895 (map (lambda (ref)
2896 (cons ref (definitions-in (current-module) ref)))
2897 various-refs)
2898 (definitions-in (current-module) (car various-refs)))))
2899
2900(define-public (lls . various-refs)
2901 (and various-refs
2902 (if (cdr various-refs)
2903 (map (lambda (ref)
2904 (cons ref (local-definitions-in (current-module) ref)))
2905 various-refs)
2906 (local-definitions-in (current-module) (car various-refs)))))
2907
0dd5491c 2908(define-public (recursive-local-define name value)
0f2d19dd
JB
2909 (let ((parent (reverse! (cdr (reverse name)))))
2910 (and parent (make-modules-in (current-module) parent))
0dd5491c 2911 (local-define name value)))
0f2d19dd
JB
2912\f
2913(define-module (ice-9 q))
2914
2915;;;; Copyright (C) 1995 Free Software Foundation, Inc.
2916;;;;
2917;;;; This program is free software; you can redistribute it and/or modify
2918;;;; it under the terms of the GNU General Public License as published by
2919;;;; the Free Software Foundation; either version 2, or (at your option)
2920;;;; any later version.
2921;;;;
2922;;;; This program is distributed in the hope that it will be useful,
2923;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
2924;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2925;;;; GNU General Public License for more details.
2926;;;;
2927;;;; You should have received a copy of the GNU General Public License
2928;;;; along with this software; see the file COPYING. If not, write to
2929;;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
2930;;;;
2931
2932\f
2933;;;;
2934;;; Q: Based on the interface to
2935;;;
2936;;; "queue.scm" Queues/Stacks for Scheme
2937;;; Written by Andrew Wilcox (awilcox@astro.psu.edu) on April 1, 1992.
2938;;;
2939
2940\f
2941;;;;
2942;;; {Q}
2943;;;
2944;;; A list is just a bunch of cons pairs that follows some constrains, right?
2945;;; Association lists are the same. Hash tables are just vectors and association
2946;;; lists. You can print them, read them, write them as constants, pun them off as other data
2947;;; structures etc. This is good. This is lisp. These structures are fast and compact
2948;;; and easy to manipulate arbitrarily because of their simple, regular structure and
2949;;; non-disjointedness (associations being lists and so forth).
2950;;;
2951;;; So I figured, queues should be the same -- just a "subtype" of cons-pair
2952;;; structures in general.
2953;;;
2954;;; A queue is a cons pair:
2955;;; ( <the-q> . <last-pair> )
2956;;;
2957;;; <the-q> is a list of things in the q. New elements go at the end of that list.
2958;;;
2959;;; <last-pair> is #f if the q is empty, and otherwise is the last pair of <the-q>.
2960;;;
2961;;; q's print nicely, but alas, they do not read well because the eq?-ness of
2962;;; <last-pair> and (last-pair <the-q>) is lost by read. The procedure
2963;;;
2964;;; (sync-q! q)
2965;;;
2966;;; recomputes and resets the <last-pair> component of a queue.
2967;;;
2968
2969(define-public (sync-q! obj) (set-cdr! obj (and (car obj) (last-pair (car obj)))))
2970
2971;;; make-q
2972;;; return a new q.
2973;;;
2974(define-public (make-q) (cons '() '()))
2975
2976;;; q? obj
2977;;; Return true if obj is a Q.
2978;;; An object is a queue if it is equal? to '(#f . #f) or
2979;;; if it is a pair P with (list? (car P)) and (eq? (cdr P) (last-pair P)).
2980;;;
2981(define-public (q? obj) (and (pair? obj)
2982 (or (and (null? (car obj))
2983 (null? (cdr obj)))
2984 (and
2985 (list? (car obj))
2986 (eq? (cdr obj) (last-pair (car obj)))))))
2987
2988;;; q-empty? obj
2989;;;
2990(define-public (q-empty? obj) (null? (car obj)))
2991
2992;;; q-empty-check q
2993;;; Throw a q-empty exception if Q is empty.
2994(define-public (q-empty-check q) (if (q-empty? q) (throw 'q-empty q)))
2995
2996
2997;;; q-front q
2998;;; Return the first element of Q.
2999(define-public (q-front q) (q-empty-check q) (caar q))
3000
3001;;; q-front q
3002;;; Return the last element of Q.
3003(define-public (q-rear q) (q-empty-check q) (cadr q))
3004
3005;;; q-remove! q obj
3006;;; Remove all occurences of obj from Q.
3007(define-public (q-remove! q obj)
3008 (while (memq obj (car q))
3009 (set-car! q (delq! obj (car q))))
3010 (set-cdr! q (last-pair (car q))))
3011
3012;;; q-push! q obj
3013;;; Add obj to the front of Q
3014(define-public (q-push! q d)
3015 (let ((h (cons d (car q))))
3016 (set-car! q h)
3017 (if (null? (cdr q))
3018 (set-cdr! q h))))
3019
3020;;; enq! q obj
3021;;; Add obj to the rear of Q
3022(define-public (enq! q d)
3023 (let ((h (cons d '())))
3024 (if (not (null? (cdr q)))
3025 (set-cdr! (cdr q) h)
3026 (set-car! q h))
3027 (set-cdr! q h)))
3028
3029;;; q-pop! q
3030;;; Take the front of Q and return it.
3031(define-public (q-pop! q)
3032 (q-empty-check q)
3033 (let ((it (caar q))
3034 (next (cdar q)))
3035 (if (not next)
3036 (set-cdr! q #f))
3037 (set-car! q next)
3038 it))
3039
3040;;; deq! q
3041;;; Take the front of Q and return it.
3042(define-public deq! q-pop!)
3043
3044;;; q-length q
3045;;; Return the number of enqueued elements.
3046;;;
3047(define-public (q-length q) (length (car q)))
3048
3049
3050
3051\f
3052;;; installed-scm-file
3053(define-module (ice-9 runq)
3054 :use-module (ice-9 q))
3055
3056\f
3057
3058;;;; Copyright (C) 1996 Free Software Foundation, Inc.
3059;;;;
3060;;;; This program is free software; you can redistribute it and/or modify
3061;;;; it under the terms of the GNU General Public License as published by
3062;;;; the Free Software Foundation; either version 2, or (at your option)
3063;;;; any later version.
3064;;;;
3065;;;; This program is distributed in the hope that it will be useful,
3066;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
3067;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3068;;;; GNU General Public License for more details.
3069;;;;
3070;;;; You should have received a copy of the GNU General Public License
3071;;;; along with this software; see the file COPYING. If not, write to
3072;;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
3073;;;;
3074
3075
3076\f
3077;;;;
3078;;; {The runq data structure}
3079;;;
3080;;; One way to schedule parallel computations in a serial environment is
3081;;; to explicitly divide each task up into small, finite execution time,
3082;;; strips. Then you interleave the execution of strips from various
3083;;; tasks to achieve a kind of parallelism. Runqs are a handy data
3084;;; structure for this style of programming.
3085;;;
3086;;; We use thunks (nullary procedures) and lists of thunks to represent
3087;;; strips. By convention, the return value of a strip-thunk must either
3088;;; be another strip or the value #f.
3089;;;
3090;;; A runq is a procedure that manages a queue of strips. Called with no
3091;;; arguments, it processes one strip from the queue. Called with
3092;;; arguments, the arguments form a control message for the queue. The
3093;;; first argument is a symbol which is the message selector.
3094;;;
3095;;; A strip is processed this way: If the strip is a thunk, the thunk is
3096;;; called -- if it returns a strip, that strip is added back to the
3097;;; queue. To process a strip which is a list of thunks, the CAR of that
3098;;; list is called. After a call to that CAR, there are 0, 1, or 2 strips
3099;;; -- perhaps one returned by the thunk, and perhaps the CDR of the
3100;;; original strip if that CDR is not nil. The runq puts whichever of
3101;;; these strips exist back on the queue. (The exact order in which
3102;;; strips are put back on the queue determines the scheduling behavior of
3103;;; a particular queue -- it's a parameter.)
3104;;;
3105;;;
3106
3107
3108
3109;;;;
3110;;; (runq-control q msg . args)
3111;;;
3112;;; processes in the default way the control messages that
3113;;; can be sent to a runq. Q should be an ordinary
3114;;; Q (see utils/q.scm).
3115;;;
3116;;; The standard runq messages are:
3117;;;
3118;;; 'add! strip0 strip1... ;; to enqueue one or more strips
3119;;; 'enqueue! strip0 strip1... ;; to enqueue one or more strips
3120;;; 'push! strip0 ... ;; add strips to the front of the queue
3121;;; 'empty? ;; true if it is
3122;;; 'length ;; how many strips in the queue?
3123;;; 'kill! ;; empty the queue
3124;;; else ;; throw 'not-understood
3125;;;
3126(define-public (runq-control q msg . args)
3127 (case msg
3128 ((add!) (for-each (lambda (t) (enq! q t)) args) '*unspecified*)
3129 ((enque!) (for-each (lambda (t) (enq! q t)) args) '*unspecified*)
3130 ((push!) (for-each (lambda (t) (q-push! q t)) args) '*unspecified*)
3131 ((empty?) (q-empty? q))
3132 ((length) (q-length q))
3133 ((kill!) (set! q (make-q)))
3134 (else (throw 'not-understood msg args))))
3135
3136(define (run-strip thunk) (catch #t thunk (lambda ign (warn 'runq-strip thunk ign) #f)))
3137
3138;;;;
3139;;; make-void-runq
3140;;;
3141;;; Make a runq that discards all messages except "length", for which
3142;;; it returns 0.
3143;;;
3144(define-public (make-void-runq)
3145 (lambda opts
3146 (and opts
3147 (apply-to-args opts
3148 (lambda (msg . args)
3149 (case msg
3150 ((length) 0)
3151 (else #f)))))))
3152
3153;;;;
3154;;; (make-fair-runq)
3155;;;
3156;;; Returns a runq procedure.
3157;;; Called with no arguments, the procedure processes one strip from the queue.
3158;;; Called with arguments, it uses runq-control.
3159;;;
3160;;; In a fair runq, if a strip returns a new strip X, X is added
3161;;; to the end of the queue, meaning it will be the last to execute
3162;;; of all the remaining procedures.
3163;;;
3164(define-public (make-fair-runq)
3165 (letrec ((q (make-q))
3166 (self
3167 (lambda ctl
3168 (if ctl
3169 (apply runq-control q ctl)
3170 (and (not (q-empty? q))
3171 (let ((next-strip (deq! q)))
3172 (cond
3173 ((procedure? next-strip) (let ((k (run-strip next-strip)))
3174 (and k (enq! q k))))
3175 ((pair? next-strip) (let ((k (run-strip (car next-strip))))
3176 (and k (enq! q k)))
3177 (if (not (null? (cdr next-strip)))
3178 (enq! q (cdr next-strip)))))
3179 self))))))
3180 self))
3181
3182
3183;;;;
3184;;; (make-exclusive-runq)
3185;;;
3186;;; Returns a runq procedure.
3187;;; Called with no arguments, the procedure processes one strip from the queue.
3188;;; Called with arguments, it uses runq-control.
3189;;;
3190;;; In an exclusive runq, if a strip W returns a new strip X, X is added
3191;;; to the front of the queue, meaning it will be the next to execute
3192;;; of all the remaining procedures.
3193;;;
3194;;; An exception to this occurs if W was the CAR of a list of strips.
3195;;; In that case, after the return value of W is pushed onto the front
3196;;; of the queue, the CDR of the list of strips is pushed in front
3197;;; of that (if the CDR is not nil). This way, the rest of the thunks
3198;;; in the list that contained W have priority over the return value of W.
3199;;;
3200(define-public (make-exclusive-runq)
3201 (letrec ((q (make-q))
3202 (self
3203 (lambda ctl
3204 (if ctl
3205 (apply runq-control q ctl)
3206 (and (not (q-empty? q))
3207 (let ((next-strip (deq! q)))
3208 (cond
3209 ((procedure? next-strip) (let ((k (run-strip next-strip)))
3210 (and k (q-push! q k))))
3211 ((pair? next-strip) (let ((k (run-strip (car next-strip))))
3212 (and k (q-push! q k)))
3213 (if (not (null? (cdr next-strip)))
3214 (q-push! q (cdr next-strip)))))
3215 self))))))
3216 self))
3217
3218
3219;;;;
3220;;; (make-subordinate-runq-to superior basic-inferior)
3221;;;
3222;;; Returns a runq proxy for the runq basic-inferior.
3223;;;
3224;;; The proxy watches for operations on the basic-inferior that cause
3225;;; a transition from a queue length of 0 to a non-zero length and
3226;;; vice versa. While the basic-inferior queue is not empty,
3227;;; the proxy installs a task on the superior runq. Each strip
3228;;; of that task processes N strips from the basic-inferior where
3229;;; N is the length of the basic-inferior queue when the proxy
3230;;; strip is entered. [Countless scheduling variations are possible.]
3231;;;
3232(define-public (make-subordinate-runq-to superior-runq basic-runq)
3233 (let ((runq-task (cons #f #f)))
3234 (set-car! runq-task
3235 (lambda ()
3236 (if (basic-runq 'empty?)
3237 (set-cdr! runq-task #f)
3238 (do ((n (basic-runq 'length) (1- n)))
3239 ((<= n 0) #f)
3240 (basic-runq)))))
3241 (letrec ((self
3242 (lambda ctl
3243 (if (not ctl)
3244 (let ((answer (basic-runq)))
3245 (self 'empty?)
3246 answer)
3247 (begin
3248 (case (car ctl)
3249 ((suspend) (set-cdr! runq-task #f))
3250 (else (let ((answer (apply basic-runq ctl)))
3251 (if (and (not (cdr runq-task)) (not (basic-runq 'empty?)))
3252 (begin
3253 (set-cdr! runq-task runq-task)
3254 (superior-runq 'add! runq-task)))
3255 answer))))))))
3256 self)))
3257
3258;;;;
3259;;; (define fork-strips (lambda args args))
3260;;; Return a strip that starts several strips in
3261;;; parallel. If this strip is enqueued on a fair
3262;;; runq, strips of the parallel subtasks will run
3263;;; round-robin style.
3264;;;
3265(define fork-strips (lambda args args))
3266
3267
3268;;;;
3269;;; (strip-sequence . strips)
3270;;;
3271;;; Returns a new strip which is the concatenation of the argument strips.
3272;;;
3273(define-public ((strip-sequence . strips))
3274 (let loop ((st (let ((a strips)) (set! strips #f) a)))
3275 (and (not (null? st))
3276 (let ((then ((car st))))
3277 (if then
3278 (lambda () (loop (cons then (cdr st))))
3279 (lambda () (loop (cdr st))))))))
3280
3281
3282;;;;
3283;;; (fair-strip-subtask . initial-strips)
3284;;;
3285;;; Returns a new strip which is the synchronos, fair,
3286;;; parallel execution of the argument strips.
3287;;;
3288;;;
3289;;;
3290(define-public (fair-strip-subtask . initial-strips)
3291 (let ((st (make-fair-runq)))
3292 (apply st 'add! initial-strips)
3293 st))
3294
3295\f
3296
3297;;; installed-scm-file
3298\f
3299(define-module (ice-9 string-fun))
3300
3301\f
3302;;;;
3303;;; {String Fun}
3304;;;
3305;;; Various string funcitons, particularly those that take
3306;;; advantage of the "shared substring" capability.
3307;;;
3308\f
3309;;;;
3310;;; {Dividing Strings Into Fields}
3311;;;
3312;;; The names of these functions are very regular.
3313;;; Here is a grammar of a call to one of these:
3314;;;
3315;;; <string-function-invocation>
3316;;; := (<action>-<seperator-disposition>-<seperator-determination> <seperator-param> <str> <ret>)
3317;;;
3318;;; <str> = the string
3319;;;
3320;;; <ret> = The continuation. String functions generally return
3321;;; multiple values by passing them to this procedure.
3322;;;
3323;;; <action> = split
3324;;; | separate-fields
3325;;;
3326;;; "split" means to divide a string into two parts.
3327;;; <ret> will be called with two arguments.
3328;;;
3329;;; "separate-fields" means to divide a string into as many
3330;;; parts as possible. <ret> will be called with
3331;;; however many fields are found.
3332;;;
3333;;; <seperator-disposition> = before
3334;;; | after
3335;;; | discarding
3336;;;
3337;;; "before" means to leave the seperator attached to
3338;;; the beginning of the field to its right.
3339;;; "after" means to leave the seperator attached to
3340;;; the end of the field to its left.
3341;;; "discarding" means to discard seperators.
3342;;;
3343;;; Other dispositions might be handy. For example, "isolate"
3344;;; could mean to treat the separator as a field unto itself.
3345;;;
3346;;; <seperator-determination> = char
3347;;; | predicate
3348;;;
3349;;; "char" means to use a particular character as field seperator.
3350;;; "predicate" means to check each character using a particular predicate.
3351;;;
3352;;; Other determinations might be handy. For example, "character-set-member".
3353;;;
3354;;; <seperator-param> = A parameter that completes the meaning of the determinations.
3355;;; For example, if the determination is "char", then this parameter
3356;;; says which character. If it is "predicate", the parameter is the
3357;;; predicate.
3358;;;
3359;;;
3360;;; For example:
3361;;;
3362;;; (separate-fields-discarding-char #\, "foo, bar, baz, , bat" list)
3363;;; => ("foo" " bar" " baz" " " " bat")
3364;;;
3365;;; (split-after-char #\- 'an-example-of-split list)
3366;;; => ("an-" "example-of-split")
3367;;;
3368;;; As an alternative to using a determination "predicate", or to trying to do anything
3369;;; complicated with these functions, consider using regular expressions.
3370;;;
3371
3372(define-public (split-after-char char str ret)
3373 (let ((end (cond
3374 ((string-index str char) => 1+)
3375 (else (string-length str)))))
3376 (ret (make-shared-substring str 0 end)
3377 (make-shared-substring str end))))
3378
3379(define-public (split-before-char char str ret)
3380 (let ((end (or (string-index str char)
3381 (string-length str))))
3382 (ret (make-shared-substring str 0 end)
3383 (make-shared-substring str end))))
3384
3385(define-public (split-discarding-char char str ret)
3386 (let ((end (string-index str char)))
3387 (if (not end)
3388 (ret str "")
3389 (ret (make-shared-substring str 0 end)
3390 (make-shared-substring str (1+ end))))))
3391
3392(define-public (split-after-char-last char str ret)
3393 (let ((end (cond
3394 ((string-rindex str char) => 1+)
3395 (else 0))))
3396 (ret (make-shared-substring str 0 end)
3397 (make-shared-substring str end))))
3398
3399(define-public (split-before-char-last char str ret)
3400 (let ((end (or (string-rindex str char) 0)))
3401 (ret (make-shared-substring str 0 end)
3402 (make-shared-substring str end))))
3403
3404(define-public (split-discarding-char-last char str ret)
3405 (let ((end (string-rindex str char)))
3406 (if (not end)
3407 (ret str "")
3408 (ret (make-shared-substring str 0 end)
3409 (make-shared-substring str (1+ end))))))
3410
3411(define (split-before-predicate pred str ret)
3412 (let loop ((n 0))
3413 (cond
3414 ((= n (length str)) (ret str ""))
3415 ((not (pred (string-ref str n))) (loop (1+ n)))
3416 (else (ret (make-shared-substring str 0 n)
3417 (make-shared-substring str n))))))
3418(define (split-after-predicate pred str ret)
3419 (let loop ((n 0))
3420 (cond
3421 ((= n (length str)) (ret str ""))
3422 ((not (pred (string-ref str n))) (loop (1+ n)))
3423 (else (ret (make-shared-substring str 0 (1+ n))
3424 (make-shared-substring str (1+ n)))))))
3425
3426(define (split-discarding-predicate pred str ret)
3427 (let loop ((n 0))
3428 (cond
3429 ((= n (length str)) (ret str ""))
3430 ((not (pred (string-ref str n))) (loop (1+ n)))
3431 (else (ret (make-shared-substring str 0 n)
3432 (make-shared-substring str (1+ n)))))))
3433
3434(define-public (seperate-fields-discarding-char ch str ret)
3435 (let loop ((fields '())
3436 (str str))
3437 (cond
3438 ((string-rindex str ch)
3439 => (lambda (pos) (loop (cons (make-shared-substring str (+ 1 w)) fields)
3440 (make-shared-substring str 0 w))))
3441 (else (ret (cons str fields))))))
3442
3443(define-public (seperate-fields-after-char ch str ret)
3444 (let loop ((fields '())
3445 (str str))
3446 (cond
3447 ((string-rindex str ch)
3448 => (lambda (pos) (loop (cons (make-shared-substring str (+ 1 w)) fields)
3449 (make-shared-substring str 0 (+ 1 w)))))
3450 (else (ret (cons str fields))))))
3451
3452(define-public (seperate-fields-before-char ch str ret)
3453 (let loop ((fields '())
3454 (str str))
3455 (cond
3456 ((string-rindex str ch)
3457 => (lambda (pos) (loop (cons (make-shared-substring str w) fields)
3458 (make-shared-substring str 0 w))))
3459 (else (ret (cons str fields))))))
3460
3461\f
3462;;;;
3463;;; {String Prefix Predicates}
3464;;;
3465;;; Very simple:
3466;;;
3467:;; (define-public ((string-prefix-predicate pred?) prefix str)
3468;;; (and (<= (length prefix) (length str))
3469;;; (pred? prefix (make-shared-substring str 0 (length prefix)))))
3470;;;
3471;;; (define-public string-prefix=? (string-prefix-predicate string=?))
3472;;;
3473
3474(define-public ((string-prefix-predicate pred?) prefix str)
3475 (and (<= (length prefix) (length str))
3476 (pred? prefix (make-shared-substring str 0 (length prefix)))))
3477
3478(define-public string-prefix=? (string-prefix-predicate string=?))
3479
3480\f
3481;;;;
3482;;; {Strippers}
3483;;;
3484;;; <stripper> = sans-<removable-part>
3485;;;
3486;;; <removable-part> = surrounding-whitespace
3487;;; | trailing-whitespace
3488;;; | leading-whitespace
3489;;; | final-newline
3490;;;
3491
3492(define-public (sans-surrounding-whitespace s)
3493 (let ((st 0)
3494 (end (string-length s)))
3495 (while (and (< st (string-length s))
3496 (char-whitespace? (string-ref s st)))
3497 (set! st (1+ st)))
3498 (while (and (< 0 end)
3499 (char-whitespace? (string-ref s (1- end))))
3500 (set! end (1- end)))
3501 (if (< end st)
3502 ""
3503 (make-shared-substring s st end))))
3504
3505(define-public (sans-trailing-whitespace s)
3506 (let ((st 0)
3507 (end (string-length s)))
3508 (while (and (< 0 end)
3509 (char-whitespace? (string-ref s (1- end))))
3510 (set! end (1- end)))
3511 (if (< end st)
3512 ""
3513 (make-shared-substring s st end))))
3514
3515(define-public (sans-leading-whitespace s)
3516 (let ((st 0)
3517 (end (string-length s)))
3518 (while (and (< st (string-length s))
3519 (char-whitespace? (string-ref s st)))
3520 (set! st (1+ st)))
3521 (if (< end st)
3522 ""
3523 (make-shared-substring s st end))))
3524
3525(define-public (sans-final-newline str)
3526 (cond
3527 ((= 0 (string-length str))
3528 str)
3529
3530 ((char=? #\nl (string-ref str (1- (string-length str))))
3531 (make-shared-substring str 0 (1- (string-length str))))
3532
3533 (else str)))
3534\f
3535;;;;
3536;;; {has-trailing-newline?}
3537;;;
3538
3539(define-public (has-trailing-newline? str)
3540 (and (< 0 (string-length str))
3541 (char=? #\nl (string-ref str (1- (string-length str))))))
3542
3543
3544\f
3545
3546
3547(define-public (with-regexp-parts regexp fields str return fail)
3548 (let ((parts (regexec regexp str fields)))
3549 (if (number? parts)
3550 (fail parts)
3551 (apply return parts))))
3552
3553\f
3554
c56634ba
MD
3555;;; {Load debug extension code if debug extensions present.}
3556;;;
3557;;; *fixme* This is a temporary solution.
3558;;;
0f2d19dd 3559
c56634ba
MD
3560(if (memq 'debug-extensions *features*)
3561 (define-module (guile) :use-module (ice-9 debug))
3562 (define-module (guile)))