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