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