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