Deprecate `id'.
[bpt/guile.git] / ice-9 / boot-9.scm
CommitLineData
0f2d19dd
JB
1;;; installed-scm-file
2
704f4e86 3;;;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
0f2d19dd
JB
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
15328041
JB
17;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18;;;; Boston, MA 02111-1307 USA
0f2d19dd
JB
19;;;;
20\f
21
22;;; This file is the first thing loaded into Guile. It adds many mundane
23;;; definitions and a few that are interesting.
24;;;
25;;; The module system (hence the hierarchical namespace) are defined in this
26;;; file.
27;;;
28
29\f
21ed9efe
MD
30;;; {Features}
31;;
32
33(define (provide sym)
34 (if (not (memq sym *features*))
35 (set! *features* (cons sym *features*))))
36
50706e94
JB
37;;; Return #t iff FEATURE is available to this Guile interpreter.
38;;; In SLIB, provided? also checks to see if the module is available.
39;;; We should do that too, but don't.
40(define (provided? feature)
41 (and (memq feature *features*) #t))
42
52cfc69b
GH
43;;; presumably deprecated.
44(define feature? provided?)
45
8641dd9e
GB
46;;; let format alias simple-format until the more complete version is loaded
47(define format simple-format)
48
21ed9efe 49\f
79451588
JB
50;;; {R4RS compliance}
51
52(primitive-load-path "ice-9/r4rs.scm")
53
54\f
44cf1f0f 55;;; {Simple Debugging Tools}
0f2d19dd
JB
56;;
57
58
59;; peek takes any number of arguments, writes them to the
60;; current ouput port, and returns the last argument.
61;; It is handy to wrap around an expression to look at
62;; a value each time is evaluated, e.g.:
63;;
64;; (+ 10 (troublesome-fn))
65;; => (+ 10 (pk 'troublesome-fn-returned (troublesome-fn)))
66;;
67
68(define (peek . stuff)
69 (newline)
70 (display ";;; ")
71 (write stuff)
72 (newline)
73 (car (last-pair stuff)))
74
75(define pk peek)
76
77(define (warn . stuff)
78 (with-output-to-port (current-error-port)
79 (lambda ()
80 (newline)
81 (display ";;; WARNING ")
6355358a 82 (display stuff)
0f2d19dd
JB
83 (newline)
84 (car (last-pair stuff)))))
85
86\f
79451588 87;;; {Trivial Functions}
0f2d19dd 88;;;
79451588 89
6b08d75b 90(define (identity x) x)
79451588
JB
91(define (1+ n) (+ n 1))
92(define (-1+ n) (+ n -1))
93(define 1- -1+)
94(define return-it noop)
132e5fac 95(define (and=> value procedure) (and value (procedure value)))
79451588
JB
96(define (make-hash-table k) (make-vector k '()))
97
0f2d19dd
JB
98;;; apply-to-args is functionally redunant with apply and, worse,
99;;; is less general than apply since it only takes two arguments.
100;;;
101;;; On the other hand, apply-to-args is a syntacticly convenient way to
102;;; perform binding in many circumstances when the "let" family of
103;;; of forms don't cut it. E.g.:
104;;;
105;;; (apply-to-args (return-3d-mouse-coords)
106;;; (lambda (x y z)
107;;; ...))
108;;;
109
110(define (apply-to-args args fn) (apply fn args))
111
112\f
6b08d75b
KN
113;;; {Deprecation}
114;;;
115
116(define call-with-deprecation
117 (let ((issued-warnings (make-hash-table 13)))
118 (lambda (msg thunk)
119 (cond ((not (hashv-ref issued-warnings msg #f))
120 (display ";;; " (current-error-port))
121 (display msg (current-error-port))
122 (newline (current-error-port))
123 (hashv-set! issued-warnings msg #t)))
124 (thunk))))
125
126(define (id x)
127 (call-with-deprecation "`id' is deprecated. Use `identity' instead."
128 (lambda ()
129 (identity x))))
130
131\f
0f2d19dd
JB
132;;; {Integer Math}
133;;;
134
0f2d19dd
JB
135(define (ipow-by-squaring x k acc proc)
136 (cond ((zero? k) acc)
137 ((= 1 k) (proc acc x))
52c5a23a
JB
138 (else (ipow-by-squaring (proc x x)
139 (quotient k 2)
140 (if (even? k) acc (proc acc x))
141 proc))))
0f2d19dd
JB
142
143(define string-character-length string-length)
144
145
146
147;; A convenience function for combining flag bits. Like logior, but
148;; handles the cases of 0 and 1 arguments.
149;;
150(define (flags . args)
151 (cond
152 ((null? args) 0)
153 ((null? (cdr args)) (car args))
154 (else (apply logior args))))
155
156\f
0f2d19dd
JB
157;;; {Symbol Properties}
158;;;
159
160(define (symbol-property sym prop)
161 (let ((pair (assoc prop (symbol-pref sym))))
162 (and pair (cdr pair))))
163
164(define (set-symbol-property! sym prop val)
165 (let ((pair (assoc prop (symbol-pref sym))))
166 (if pair
167 (set-cdr! pair val)
168 (symbol-pset! sym (acons prop val (symbol-pref sym))))))
169
170(define (symbol-property-remove! sym prop)
171 (let ((pair (assoc prop (symbol-pref sym))))
172 (if pair
173 (symbol-pset! sym (delq! pair (symbol-pref sym))))))
174
2d55a919
MV
175;;; {General Properties}
176
177;; This is a more modern interface to properties. It will replace all
178;; other property-like things eventually.
179
180(define (make-object-property)
181 (let ((prop (primitive-make-property #f)))
182 (make-procedure-with-setter
183 (lambda (obj) (primitive-property-ref prop obj))
184 (lambda (obj val) (primitive-property-set! prop obj val)))))
185
0f2d19dd 186\f
1e531c3a 187
0f2d19dd
JB
188;;; {Arrays}
189;;;
190
afe5177e
GH
191(if (provided? 'array)
192 (primitive-load-path "ice-9/arrays.scm"))
0f2d19dd
JB
193
194\f
195;;; {Keywords}
196;;;
197
198(define (symbol->keyword symbol)
199 (make-keyword-from-dash-symbol (symbol-append '- symbol)))
200
201(define (keyword->symbol kw)
06f0414c 202 (let ((sym (symbol->string (keyword-dash-symbol kw))))
11b05261 203 (string->symbol (substring sym 1 (string-length sym)))))
0f2d19dd
JB
204
205(define (kw-arg-ref args kw)
206 (let ((rem (member kw args)))
207 (and rem (pair? (cdr rem)) (cadr rem))))
208
209\f
fa7e9274 210
9f9aa47b 211;;; {Structs}
fa7e9274
MV
212
213(define (struct-layout s)
9f9aa47b 214 (struct-ref (struct-vtable s) vtable-index-layout))
fa7e9274
MV
215
216\f
d7faeb2e
MD
217
218;;; Environments
219
220(define the-environment
221 (procedure->syntax
222 (lambda (x e)
223 e)))
224
225(define the-root-environment (the-environment))
226
227(define (environment-module env)
228 (let ((closure (and (pair? env) (car (last-pair env)))))
229 (and closure (procedure-property closure 'module))))
230
231\f
0f2d19dd
JB
232;;; {Records}
233;;;
234
fa7e9274
MV
235;; Printing records: by default, records are printed as
236;;
237;; #<type-name field1: val1 field2: val2 ...>
238;;
239;; You can change that by giving a custom printing function to
240;; MAKE-RECORD-TYPE (after the list of field symbols). This function
241;; will be called like
242;;
243;; (<printer> object port)
244;;
245;; It should print OBJECT to PORT.
246
cf8f1a90 247(define (inherit-print-state old-port new-port)
8a30733e
MD
248 (if (get-print-state old-port)
249 (port-with-print-state new-port (get-print-state old-port))
cf8f1a90
MV
250 new-port))
251
9f9aa47b 252;; 0: type-name, 1: fields
fa7e9274 253(define record-type-vtable
9f9aa47b
MD
254 (make-vtable-vtable "prpr" 0
255 (lambda (s p)
256 (cond ((eq? s record-type-vtable)
257 (display "#<record-type-vtable>" p))
258 (else
259 (display "#<record-type " p)
260 (display (record-type-name s) p)
261 (display ">" p))))))
0f2d19dd
JB
262
263(define (record-type? obj)
264 (and (struct? obj) (eq? record-type-vtable (struct-vtable obj))))
265
266(define (make-record-type type-name fields . opt)
8e693424 267 (let ((printer-fn (and (pair? opt) (car opt))))
0f2d19dd 268 (let ((struct (make-struct record-type-vtable 0
c7c03b9f 269 (make-struct-layout
06f0414c 270 (apply string-append
c7c03b9f 271 (map (lambda (f) "pw") fields)))
9f9aa47b
MD
272 (or printer-fn
273 (lambda (s p)
274 (display "#<" p)
275 (display type-name p)
276 (let loop ((fields fields)
277 (off 0))
278 (cond
279 ((not (null? fields))
280 (display " " p)
281 (display (car fields) p)
282 (display ": " p)
283 (display (struct-ref s off) p)
284 (loop (cdr fields) (+ 1 off)))))
285 (display ">" p)))
0f2d19dd
JB
286 type-name
287 (copy-tree fields))))
c8eed875
MD
288 ;; Temporary solution: Associate a name to the record type descriptor
289 ;; so that the object system can create a wrapper class for it.
290 (set-struct-vtable-name! struct (if (symbol? type-name)
291 type-name
292 (string->symbol type-name)))
0f2d19dd
JB
293 struct)))
294
295(define (record-type-name obj)
296 (if (record-type? obj)
9f9aa47b 297 (struct-ref obj vtable-offset-user)
0f2d19dd
JB
298 (error 'not-a-record-type obj)))
299
300(define (record-type-fields obj)
301 (if (record-type? obj)
9f9aa47b 302 (struct-ref obj (+ 1 vtable-offset-user))
0f2d19dd
JB
303 (error 'not-a-record-type obj)))
304
305(define (record-constructor rtd . opt)
8e693424 306 (let ((field-names (if (pair? opt) (car opt) (record-type-fields rtd))))
d7faeb2e
MD
307 (local-eval `(lambda ,field-names
308 (make-struct ',rtd 0 ,@(map (lambda (f)
309 (if (memq f field-names)
310 f
311 #f))
312 (record-type-fields rtd))))
313 the-root-environment)))
0f2d19dd
JB
314
315(define (record-predicate rtd)
316 (lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj)))))
317
318(define (record-accessor rtd field-name)
319 (let* ((pos (list-index (record-type-fields rtd) field-name)))
320 (if (not pos)
321 (error 'no-such-field field-name))
d7faeb2e
MD
322 (local-eval `(lambda (obj)
323 (and (eq? ',rtd (record-type-descriptor obj))
324 (struct-ref obj ,pos)))
325 the-root-environment)))
0f2d19dd
JB
326
327(define (record-modifier rtd field-name)
328 (let* ((pos (list-index (record-type-fields rtd) field-name)))
329 (if (not pos)
330 (error 'no-such-field field-name))
d7faeb2e
MD
331 (local-eval `(lambda (obj val)
332 (and (eq? ',rtd (record-type-descriptor obj))
333 (struct-set! obj ,pos val)))
334 the-root-environment)))
0f2d19dd
JB
335
336
337(define (record? obj)
338 (and (struct? obj) (record-type? (struct-vtable obj))))
339
340(define (record-type-descriptor obj)
341 (if (struct? obj)
342 (struct-vtable obj)
343 (error 'not-a-record obj)))
344
21ed9efe
MD
345(provide 'record)
346
0f2d19dd
JB
347\f
348;;; {Booleans}
349;;;
350
351(define (->bool x) (not (not x)))
352
353\f
354;;; {Symbols}
355;;;
356
357(define (symbol-append . args)
06f0414c 358 (string->symbol (apply string-append (map symbol->string args))))
0f2d19dd
JB
359
360(define (list->symbol . args)
361 (string->symbol (apply list->string args)))
362
363(define (symbol . args)
364 (string->symbol (apply string args)))
365
0f2d19dd
JB
366\f
367;;; {Lists}
368;;;
369
370(define (list-index l k)
371 (let loop ((n 0)
372 (l l))
373 (and (not (null? l))
374 (if (eq? (car l) k)
375 n
376 (loop (+ n 1) (cdr l))))))
377
75fd4fb6
JB
378(define (make-list n . init)
379 (if (pair? init) (set! init (car init)))
0f2d19dd
JB
380 (let loop ((answer '())
381 (n n))
382 (if (<= n 0)
383 answer
384 (loop (cons init answer) (- n 1)))))
385
1729d8ff 386\f
3e3cec45 387;;; {and-map and or-map}
0f2d19dd
JB
388;;;
389;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
390;;; (or-map fn lst) is like (or (fn (car lst)) (fn (cadr lst)) (fn...) ...)
0f2d19dd
JB
391;;;
392
393;; and-map f l
394;;
395;; Apply f to successive elements of l until exhaustion or f returns #f.
396;; If returning early, return #f. Otherwise, return the last value returned
397;; by f. If f has never been called because l is empty, return #t.
398;;
399(define (and-map f lst)
400 (let loop ((result #t)
401 (l lst))
402 (and result
403 (or (and (null? l)
404 result)
405 (loop (f (car l)) (cdr l))))))
406
407;; or-map f l
408;;
409;; Apply f to successive elements of l until exhaustion or while f returns #f.
410;; If returning early, return the return value of f.
411;;
412(define (or-map f lst)
413 (let loop ((result #f)
414 (l lst))
415 (or result
416 (and (not (null? l))
417 (loop (f (car l)) (cdr l))))))
418
59e1116d 419\f
0f2d19dd 420
52cfc69b
GH
421(if (provided? 'posix)
422 (primitive-load-path "ice-9/posix.scm"))
6fa8995c 423
52cfc69b
GH
424(if (provided? 'socket)
425 (primitive-load-path "ice-9/networking.scm"))
3afb28ce 426
6fa8995c 427(define file-exists?
52cfc69b 428 (if (provided? 'posix)
6fa8995c
GH
429 (lambda (str)
430 (access? str F_OK))
431 (lambda (str)
432 (let ((port (catch 'system-error (lambda () (open-file str OPEN_READ))
433 (lambda args #f))))
434 (if port (begin (close-port port) #t)
435 #f)))))
436
437(define file-is-directory?
52cfc69b 438 (if (provided? 'posix)
6fa8995c 439 (lambda (str)
3afb28ce 440 (eq? (stat:type (stat str)) 'directory))
6fa8995c 441 (lambda (str)
6fa8995c
GH
442 (let ((port (catch 'system-error
443 (lambda () (open-file (string-append str "/.")
444 OPEN_READ))
445 (lambda args #f))))
446 (if port (begin (close-port port) #t)
447 #f)))))
0f2d19dd
JB
448
449(define (has-suffix? str suffix)
450 (let ((sufl (string-length suffix))
451 (sl (string-length str)))
452 (and (> sl sufl)
453 (string=? (substring str (- sl sufl) sl) suffix))))
454
0f2d19dd
JB
455\f
456;;; {Error Handling}
457;;;
458
0f2d19dd 459(define (error . args)
21ed9efe 460 (save-stack)
2194b6f0 461 (if (null? args)
5552355a 462 (scm-error 'misc-error #f "?" #f #f)
8641dd9e 463 (let loop ((msg "~A")
2194b6f0
GH
464 (rest (cdr args)))
465 (if (not (null? rest))
8641dd9e 466 (loop (string-append msg " ~S")
2194b6f0 467 (cdr rest))
5552355a 468 (scm-error 'misc-error #f msg args #f)))))
be2d2c70 469
1349bd53 470;; bad-throw is the hook that is called upon a throw to a an unhandled
9a0d70e2
GH
471;; key (unless the throw has four arguments, in which case
472;; it's usually interpreted as an error throw.)
473;; If the key has a default handler (a throw-handler-default property),
0f2d19dd
JB
474;; it is applied to the throw.
475;;
1349bd53 476(define (bad-throw key . args)
0f2d19dd
JB
477 (let ((default (symbol-property key 'throw-handler-default)))
478 (or (and default (apply default key args))
2194b6f0 479 (apply error "unhandled-exception:" key args))))
0f2d19dd 480
0f2d19dd 481\f
bce074ee 482
708bf0f3
GH
483(define (tm:sec obj) (vector-ref obj 0))
484(define (tm:min obj) (vector-ref obj 1))
485(define (tm:hour obj) (vector-ref obj 2))
486(define (tm:mday obj) (vector-ref obj 3))
487(define (tm:mon obj) (vector-ref obj 4))
488(define (tm:year obj) (vector-ref obj 5))
489(define (tm:wday obj) (vector-ref obj 6))
490(define (tm:yday obj) (vector-ref obj 7))
491(define (tm:isdst obj) (vector-ref obj 8))
492(define (tm:gmtoff obj) (vector-ref obj 9))
493(define (tm:zone obj) (vector-ref obj 10))
494
495(define (set-tm:sec obj val) (vector-set! obj 0 val))
496(define (set-tm:min obj val) (vector-set! obj 1 val))
497(define (set-tm:hour obj val) (vector-set! obj 2 val))
498(define (set-tm:mday obj val) (vector-set! obj 3 val))
499(define (set-tm:mon obj val) (vector-set! obj 4 val))
500(define (set-tm:year obj val) (vector-set! obj 5 val))
501(define (set-tm:wday obj val) (vector-set! obj 6 val))
502(define (set-tm:yday obj val) (vector-set! obj 7 val))
503(define (set-tm:isdst obj val) (vector-set! obj 8 val))
504(define (set-tm:gmtoff obj val) (vector-set! obj 9 val))
505(define (set-tm:zone obj val) (vector-set! obj 10 val))
506
6afcd3b2
GH
507(define (tms:clock obj) (vector-ref obj 0))
508(define (tms:utime obj) (vector-ref obj 1))
509(define (tms:stime obj) (vector-ref obj 2))
510(define (tms:cutime obj) (vector-ref obj 3))
511(define (tms:cstime obj) (vector-ref obj 4))
512
bce074ee
GH
513(define (file-position . args) (apply ftell args))
514(define (file-set-position . args) (apply fseek args))
8b13c6b3 515
e38303a2
GH
516(define (move->fdes fd/port fd)
517 (cond ((integer? fd/port)
7a6f1ffa 518 (dup->fdes fd/port fd)
e38303a2
GH
519 (close fd/port)
520 fd)
521 (else
522 (primitive-move->fdes fd/port fd)
523 (set-port-revealed! fd/port 1)
524 fd/port)))
8b13c6b3
GH
525
526(define (release-port-handle port)
527 (let ((revealed (port-revealed port)))
528 (if (> revealed 0)
529 (set-port-revealed! port (- revealed 1)))))
0f2d19dd 530
e38303a2 531(define (dup->port port/fd mode . maybe-fd)
7a6f1ffa 532 (let ((port (fdopen (apply dup->fdes port/fd maybe-fd)
e38303a2
GH
533 mode)))
534 (if (pair? maybe-fd)
535 (set-port-revealed! port 1))
536 port))
537
538(define (dup->inport port/fd . maybe-fd)
539 (apply dup->port port/fd "r" maybe-fd))
540
541(define (dup->outport port/fd . maybe-fd)
542 (apply dup->port port/fd "w" maybe-fd))
543
e38303a2
GH
544(define (dup port/fd . maybe-fd)
545 (if (integer? port/fd)
546 (apply dup->fdes port/fd maybe-fd)
547 (apply dup->port port/fd (port-mode port/fd) maybe-fd)))
548
549(define (duplicate-port port modes)
550 (dup->port port modes))
551
552(define (fdes->inport fdes)
553 (let loop ((rest-ports (fdes->ports fdes)))
554 (cond ((null? rest-ports)
555 (let ((result (fdopen fdes "r")))
556 (set-port-revealed! result 1)
557 result))
558 ((input-port? (car rest-ports))
559 (set-port-revealed! (car rest-ports)
560 (+ (port-revealed (car rest-ports)) 1))
561 (car rest-ports))
562 (else
563 (loop (cdr rest-ports))))))
564
565(define (fdes->outport fdes)
566 (let loop ((rest-ports (fdes->ports fdes)))
567 (cond ((null? rest-ports)
568 (let ((result (fdopen fdes "w")))
569 (set-port-revealed! result 1)
570 result))
571 ((output-port? (car rest-ports))
572 (set-port-revealed! (car rest-ports)
573 (+ (port-revealed (car rest-ports)) 1))
574 (car rest-ports))
575 (else
576 (loop (cdr rest-ports))))))
577
578(define (port->fdes port)
579 (set-port-revealed! port (+ (port-revealed port) 1))
580 (fileno port))
581
956055a9
GH
582(define (setenv name value)
583 (if value
584 (putenv (string-append name "=" value))
585 (putenv name)))
586
0f2d19dd
JB
587\f
588;;; {Load Paths}
589;;;
590
0f2d19dd
JB
591;;; Here for backward compatability
592;;
593(define scheme-file-suffix (lambda () ".scm"))
594
3cab8392
JB
595(define (in-vicinity vicinity file)
596 (let ((tail (let ((len (string-length vicinity)))
534a0099
MD
597 (if (zero? len)
598 #f
3cab8392
JB
599 (string-ref vicinity (- len 1))))))
600 (string-append vicinity
534a0099
MD
601 (if (or (not tail)
602 (eq? tail #\/))
603 ""
604 "/")
3cab8392 605 file)))
02ceadb8 606
0f2d19dd 607\f
ef00e7f4
JB
608;;; {Help for scm_shell}
609;;; The argument-processing code used by Guile-based shells generates
610;;; Scheme code based on the argument list. This page contains help
611;;; functions for the code it generates.
612
ef00e7f4
JB
613(define (command-line) (program-arguments))
614
5aa7fe69
JB
615;; This is mostly for the internal use of the code generated by
616;; scm_compile_shell_switches.
ef00e7f4 617(define (load-user-init)
1f08acd9
GH
618 (let* ((home (or (getenv "HOME")
619 (false-if-exception (passwd:dir (getpwuid (getuid))))
620 "/")) ;; fallback for cygwin etc.
621 (init-file (in-vicinity home ".guile")))
622 (if (file-exists? init-file)
623 (primitive-load init-file))))
ef00e7f4
JB
624
625\f
a06181a2
JB
626;;; {Loading by paths}
627
628;;; Load a Scheme source file named NAME, searching for it in the
629;;; directories listed in %load-path, and applying each of the file
630;;; name extensions listed in %load-extensions.
631(define (load-from-path name)
632 (start-stack 'load-stack
75a97b92 633 (primitive-load-path name)))
0f2d19dd 634
5552355a 635
0f2d19dd 636\f
0f2d19dd
JB
637;;; {Transcendental Functions}
638;;;
639;;; Derived from "Transcen.scm", Complex trancendental functions for SCM.
0543c9b7 640;;; Written by Jerry D. Hedden, (C) FSF.
0f2d19dd
JB
641;;; See the file `COPYING' for terms applying to this program.
642;;;
643
644(define (exp z)
645 (if (real? z) ($exp z)
646 (make-polar ($exp (real-part z)) (imag-part z))))
647
648(define (log z)
649 (if (and (real? z) (>= z 0))
650 ($log z)
651 (make-rectangular ($log (magnitude z)) (angle z))))
652
653(define (sqrt z)
654 (if (real? z)
655 (if (negative? z) (make-rectangular 0 ($sqrt (- z)))
656 ($sqrt z))
657 (make-polar ($sqrt (magnitude z)) (/ (angle z) 2))))
658
659(define expt
660 (let ((integer-expt integer-expt))
661 (lambda (z1 z2)
22381005
DH
662 (cond ((integer? z2)
663 (if (>= z2 0)
664 (integer-expt z1 z2)
665 (/ 1 (integer-expt z1 (- z2)))))
0f2d19dd
JB
666 ((and (real? z2) (real? z1) (>= z1 0))
667 ($expt z1 z2))
668 (else
669 (exp (* z2 (log z1))))))))
670
671(define (sinh z)
672 (if (real? z) ($sinh z)
673 (let ((x (real-part z)) (y (imag-part z)))
674 (make-rectangular (* ($sinh x) ($cos y))
675 (* ($cosh x) ($sin y))))))
676(define (cosh z)
677 (if (real? z) ($cosh z)
678 (let ((x (real-part z)) (y (imag-part z)))
679 (make-rectangular (* ($cosh x) ($cos y))
680 (* ($sinh x) ($sin y))))))
681(define (tanh z)
682 (if (real? z) ($tanh z)
683 (let* ((x (* 2 (real-part z)))
684 (y (* 2 (imag-part z)))
685 (w (+ ($cosh x) ($cos y))))
686 (make-rectangular (/ ($sinh x) w) (/ ($sin y) w)))))
687
688(define (asinh z)
689 (if (real? z) ($asinh z)
690 (log (+ z (sqrt (+ (* z z) 1))))))
691
692(define (acosh z)
693 (if (and (real? z) (>= z 1))
694 ($acosh z)
695 (log (+ z (sqrt (- (* z z) 1))))))
696
697(define (atanh z)
698 (if (and (real? z) (> z -1) (< z 1))
699 ($atanh z)
700 (/ (log (/ (+ 1 z) (- 1 z))) 2)))
701
702(define (sin z)
703 (if (real? z) ($sin z)
704 (let ((x (real-part z)) (y (imag-part z)))
705 (make-rectangular (* ($sin x) ($cosh y))
706 (* ($cos x) ($sinh y))))))
707(define (cos z)
708 (if (real? z) ($cos z)
709 (let ((x (real-part z)) (y (imag-part z)))
710 (make-rectangular (* ($cos x) ($cosh y))
711 (- (* ($sin x) ($sinh y)))))))
712(define (tan z)
713 (if (real? z) ($tan z)
714 (let* ((x (* 2 (real-part z)))
715 (y (* 2 (imag-part z)))
716 (w (+ ($cos x) ($cosh y))))
717 (make-rectangular (/ ($sin x) w) (/ ($sinh y) w)))))
718
719(define (asin z)
720 (if (and (real? z) (>= z -1) (<= z 1))
721 ($asin z)
722 (* -i (asinh (* +i z)))))
723
724(define (acos z)
725 (if (and (real? z) (>= z -1) (<= z 1))
726 ($acos z)
727 (+ (/ (angle -1) 2) (* +i (asinh (* +i z))))))
728
729(define (atan z . y)
730 (if (null? y)
731 (if (real? z) ($atan z)
732 (/ (log (/ (- +i z) (+ +i z))) +2i))
733 ($atan2 z (car y))))
734
65495221
GH
735(define (log10 arg)
736 (/ (log arg) (log 10)))
737
0f2d19dd 738\f
0f2d19dd
JB
739
740;;; {Reader Extensions}
741;;;
742
743;;; Reader code for various "#c" forms.
744;;;
745
75a97b92
GH
746(read-hash-extend #\' (lambda (c port)
747 (read port)))
748(read-hash-extend #\. (lambda (c port)
d7faeb2e 749 (eval (read port) (interaction-environment))))
75a97b92 750
0f2d19dd
JB
751\f
752;;; {Command Line Options}
753;;;
754
755(define (get-option argv kw-opts kw-args return)
756 (cond
757 ((null? argv)
758 (return #f #f argv))
759
760 ((or (not (eq? #\- (string-ref (car argv) 0)))
761 (eq? (string-length (car argv)) 1))
762 (return 'normal-arg (car argv) (cdr argv)))
763
764 ((eq? #\- (string-ref (car argv) 1))
765 (let* ((kw-arg-pos (or (string-index (car argv) #\=)
766 (string-length (car argv))))
767 (kw (symbol->keyword (substring (car argv) 2 kw-arg-pos)))
768 (kw-opt? (member kw kw-opts))
769 (kw-arg? (member kw kw-args))
770 (arg (or (and (not (eq? kw-arg-pos (string-length (car argv))))
771 (substring (car argv)
772 (+ kw-arg-pos 1)
773 (string-length (car argv))))
774 (and kw-arg?
775 (begin (set! argv (cdr argv)) (car argv))))))
776 (if (or kw-opt? kw-arg?)
777 (return kw arg (cdr argv))
778 (return 'usage-error kw (cdr argv)))))
779
780 (else
781 (let* ((char (substring (car argv) 1 2))
782 (kw (symbol->keyword char)))
783 (cond
784
785 ((member kw kw-opts)
786 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
787 (new-argv (if (= 0 (string-length rest-car))
788 (cdr argv)
789 (cons (string-append "-" rest-car) (cdr argv)))))
790 (return kw #f new-argv)))
791
792 ((member kw kw-args)
793 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
794 (arg (if (= 0 (string-length rest-car))
795 (cadr argv)
796 rest-car))
797 (new-argv (if (= 0 (string-length rest-car))
798 (cddr argv)
799 (cdr argv))))
800 (return kw arg new-argv)))
801
802 (else (return 'usage-error kw argv)))))))
803
804(define (for-next-option proc argv kw-opts kw-args)
805 (let loop ((argv argv))
806 (get-option argv kw-opts kw-args
807 (lambda (opt opt-arg argv)
808 (and opt (proc opt opt-arg argv loop))))))
809
810(define (display-usage-report kw-desc)
811 (for-each
812 (lambda (kw)
813 (or (eq? (car kw) #t)
814 (eq? (car kw) 'else)
815 (let* ((opt-desc kw)
816 (help (cadr opt-desc))
817 (opts (car opt-desc))
818 (opts-proper (if (string? (car opts)) (cdr opts) opts))
819 (arg-name (if (string? (car opts))
820 (string-append "<" (car opts) ">")
821 ""))
822 (left-part (string-append
823 (with-output-to-string
824 (lambda ()
825 (map (lambda (x) (display (keyword-symbol x)) (display " "))
826 opts-proper)))
827 arg-name))
11b05261
MD
828 (middle-part (if (and (< (string-length left-part) 30)
829 (< (string-length help) 40))
830 (make-string (- 30 (string-length left-part)) #\ )
0f2d19dd
JB
831 "\n\t")))
832 (display left-part)
833 (display middle-part)
834 (display help)
835 (newline))))
836 kw-desc))
837
838
839
0f2d19dd
JB
840(define (transform-usage-lambda cases)
841 (let* ((raw-usage (delq! 'else (map car cases)))
842 (usage-sans-specials (map (lambda (x)
843 (or (and (not (list? x)) x)
844 (and (symbol? (car x)) #t)
845 (and (boolean? (car x)) #t)
846 x))
847 raw-usage))
ed440df5 848 (usage-desc (delq! #t usage-sans-specials))
0f2d19dd
JB
849 (kw-desc (map car usage-desc))
850 (kw-opts (apply append (map (lambda (x) (and (not (string? (car x))) x)) kw-desc)))
851 (kw-args (apply append (map (lambda (x) (and (string? (car x)) (cdr x))) kw-desc)))
852 (transmogrified-cases (map (lambda (case)
853 (cons (let ((opts (car case)))
854 (if (or (boolean? opts) (eq? 'else opts))
855 opts
856 (cond
857 ((symbol? (car opts)) opts)
858 ((boolean? (car opts)) opts)
859 ((string? (caar opts)) (cdar opts))
860 (else (car opts)))))
861 (cdr case)))
862 cases)))
863 `(let ((%display-usage (lambda () (display-usage-report ',usage-desc))))
864 (lambda (%argv)
865 (let %next-arg ((%argv %argv))
866 (get-option %argv
867 ',kw-opts
868 ',kw-args
869 (lambda (%opt %arg %new-argv)
870 (case %opt
871 ,@ transmogrified-cases))))))))
872
873
874\f
875
876;;; {Low Level Modules}
877;;;
878;;; These are the low level data structures for modules.
879;;;
880;;; !!! warning: The interface to lazy binder procedures is going
881;;; to be changed in an incompatible way to permit all the basic
882;;; module ops to be virtualized.
883;;;
884;;; (make-module size use-list lazy-binding-proc) => module
885;;; module-{obarray,uses,binder}[|-set!]
886;;; (module? obj) => [#t|#f]
887;;; (module-locally-bound? module symbol) => [#t|#f]
888;;; (module-bound? module symbol) => [#t|#f]
889;;; (module-symbol-locally-interned? module symbol) => [#t|#f]
890;;; (module-symbol-interned? module symbol) => [#t|#f]
891;;; (module-local-variable module symbol) => [#<variable ...> | #f]
892;;; (module-variable module symbol) => [#<variable ...> | #f]
893;;; (module-symbol-binding module symbol opt-value)
894;;; => [ <obj> | opt-value | an error occurs ]
895;;; (module-make-local-var! module symbol) => #<variable...>
896;;; (module-add! module symbol var) => unspecified
897;;; (module-remove! module symbol) => unspecified
898;;; (module-for-each proc module) => unspecified
899;;; (make-scm-module) => module ; a lazy copy of the symhash module
900;;; (set-current-module module) => unspecified
901;;; (current-module) => #<module...>
902;;;
903;;;
904
905\f
44cf1f0f
JB
906;;; {Printing Modules}
907;; This is how modules are printed. You can re-define it.
fa7e9274
MV
908;; (Redefining is actually more complicated than simply redefining
909;; %print-module because that would only change the binding and not
910;; the value stored in the vtable that determines how record are
911;; printed. Sigh.)
912
913(define (%print-module mod port) ; unused args: depth length style table)
0f2d19dd
JB
914 (display "#<" port)
915 (display (or (module-kind mod) "module") port)
916 (let ((name (module-name mod)))
917 (if name
918 (begin
919 (display " " port)
920 (display name port))))
921 (display " " port)
922 (display (number->string (object-address mod) 16) port)
923 (display ">" port))
924
925;; module-type
926;;
927;; A module is characterized by an obarray in which local symbols
928;; are interned, a list of modules, "uses", from which non-local
929;; bindings can be inherited, and an optional lazy-binder which
31d50456 930;; is a (CLOSURE module symbol) which, as a last resort, can provide
0f2d19dd
JB
931;; bindings that would otherwise not be found locally in the module.
932;;
d7faeb2e
MD
933;; NOTE: If you change here, you also need to change libguile/modules.h.
934;;
0f2d19dd 935(define module-type
7a0ff2f8 936 (make-record-type 'module
1777c18b
MD
937 '(obarray uses binder eval-closure transformer name kind
938 observers weak-observers observer-id)
8b718458 939 %print-module))
0f2d19dd 940
8b718458 941;; make-module &opt size uses binder
0f2d19dd 942;;
8b718458
JB
943;; Create a new module, perhaps with a particular size of obarray,
944;; initial uses list, or binding procedure.
0f2d19dd 945;;
0f2d19dd
JB
946(define make-module
947 (lambda args
0f2d19dd 948
8b718458
JB
949 (define (parse-arg index default)
950 (if (> (length args) index)
951 (list-ref args index)
952 default))
953
954 (if (> (length args) 3)
955 (error "Too many args to make-module." args))
0f2d19dd 956
8b718458
JB
957 (let ((size (parse-arg 0 1021))
958 (uses (parse-arg 1 '()))
959 (binder (parse-arg 2 #f)))
0f2d19dd 960
8b718458
JB
961 (if (not (integer? size))
962 (error "Illegal size to make-module." size))
963 (if (not (and (list? uses)
964 (and-map module? uses)))
965 (error "Incorrect use list." uses))
0f2d19dd
JB
966 (if (and binder (not (procedure? binder)))
967 (error
968 "Lazy-binder expected to be a procedure or #f." binder))
969
8b718458 970 (let ((module (module-constructor (make-vector size '())
1777c18b
MD
971 uses binder #f #f #f #f
972 '()
973 (make-weak-value-hash-table 31)
974 0)))
8b718458
JB
975
976 ;; We can't pass this as an argument to module-constructor,
977 ;; because we need it to close over a pointer to the module
978 ;; itself.
6906bd0d 979 (set-module-eval-closure! module (standard-eval-closure module))
8b718458
JB
980
981 module))))
0f2d19dd 982
8b718458 983(define module-constructor (record-constructor module-type))
0f2d19dd
JB
984(define module-obarray (record-accessor module-type 'obarray))
985(define set-module-obarray! (record-modifier module-type 'obarray))
986(define module-uses (record-accessor module-type 'uses))
987(define set-module-uses! (record-modifier module-type 'uses))
988(define module-binder (record-accessor module-type 'binder))
989(define set-module-binder! (record-modifier module-type 'binder))
631c1902
MD
990
991;; NOTE: This binding is used in libguile/modules.c.
31d50456 992(define module-eval-closure (record-accessor module-type 'eval-closure))
631c1902 993
7a0ff2f8
MD
994(define module-transformer (record-accessor module-type 'transformer))
995(define set-module-transformer! (record-modifier module-type 'transformer))
0f2d19dd
JB
996(define module-name (record-accessor module-type 'name))
997(define set-module-name! (record-modifier module-type 'name))
998(define module-kind (record-accessor module-type 'kind))
999(define set-module-kind! (record-modifier module-type 'kind))
1777c18b
MD
1000(define module-observers (record-accessor module-type 'observers))
1001(define set-module-observers! (record-modifier module-type 'observers))
1002(define module-weak-observers (record-accessor module-type 'weak-observers))
1003(define module-observer-id (record-accessor module-type 'observer-id))
1004(define set-module-observer-id! (record-modifier module-type 'observer-id))
0f2d19dd
JB
1005(define module? (record-predicate module-type))
1006
edc185c7
MD
1007(define set-module-eval-closure!
1008 (let ((setter (record-modifier module-type 'eval-closure)))
1009 (lambda (module closure)
1010 (setter module closure)
1011 ;; Make it possible to lookup the module from the environment.
1012 ;; This implementation is correct since an eval closure can belong
1013 ;; to maximally one module.
1014 (set-procedure-property! closure 'module module))))
8b718458 1015
d7faeb2e
MD
1016;;; This procedure is depreated
1017;;;
1018(define eval-in-module eval)
0f2d19dd
JB
1019
1020\f
1777c18b
MD
1021;;; {Observer protocol}
1022;;;
1023
1024(define (module-observe module proc)
1025 (set-module-observers! module (cons proc (module-observers module)))
1026 (cons module proc))
1027
1028(define (module-observe-weak module proc)
1029 (let ((id (module-observer-id module)))
1030 (hash-set! (module-weak-observers module) id proc)
1031 (set-module-observer-id! module (+ 1 id))
1032 (cons module id)))
1033
1034(define (module-unobserve token)
1035 (let ((module (car token))
1036 (id (cdr token)))
1037 (if (integer? id)
1038 (hash-remove! (module-weak-observers module) id)
1039 (set-module-observers! module (delq1! id (module-observers module)))))
1040 *unspecified*)
1041
1a961d7e 1042(define (module-modified m)
1777c18b
MD
1043 (for-each (lambda (proc) (proc m)) (module-observers m))
1044 (hash-fold (lambda (id proc res) (proc m)) #f (module-weak-observers m)))
1045
1046\f
0f2d19dd
JB
1047;;; {Module Searching in General}
1048;;;
1049;;; We sometimes want to look for properties of a symbol
1050;;; just within the obarray of one module. If the property
1051;;; holds, then it is said to hold ``locally'' as in, ``The symbol
1052;;; DISPLAY is locally rebound in the module `safe-guile'.''
1053;;;
1054;;;
1055;;; Other times, we want to test for a symbol property in the obarray
1056;;; of M and, if it is not found there, try each of the modules in the
1057;;; uses list of M. This is the normal way of testing for some
1058;;; property, so we state these properties without qualification as
1059;;; in: ``The symbol 'fnord is interned in module M because it is
1060;;; interned locally in module M2 which is a member of the uses list
1061;;; of M.''
1062;;;
1063
1064;; module-search fn m
1065;;
1066;; return the first non-#f result of FN applied to M and then to
1067;; the modules in the uses of m, and so on recursively. If all applications
1068;; return #f, then so does this function.
1069;;
1070(define (module-search fn m v)
1071 (define (loop pos)
1072 (and (pair? pos)
1073 (or (module-search fn (car pos) v)
1074 (loop (cdr pos)))))
1075 (or (fn m v)
1076 (loop (module-uses m))))
1077
1078
1079;;; {Is a symbol bound in a module?}
1080;;;
1081;;; Symbol S in Module M is bound if S is interned in M and if the binding
1082;;; of S in M has been set to some well-defined value.
1083;;;
1084
1085;; module-locally-bound? module symbol
1086;;
1087;; Is a symbol bound (interned and defined) locally in a given module?
1088;;
1089(define (module-locally-bound? m v)
1090 (let ((var (module-local-variable m v)))
1091 (and var
1092 (variable-bound? var))))
1093
1094;; module-bound? module symbol
1095;;
1096;; Is a symbol bound (interned and defined) anywhere in a given module
1097;; or its uses?
1098;;
1099(define (module-bound? m v)
1100 (module-search module-locally-bound? m v))
1101
1102;;; {Is a symbol interned in a module?}
1103;;;
1104;;; Symbol S in Module M is interned if S occurs in
1105;;; of S in M has been set to some well-defined value.
1106;;;
1107;;; It is possible to intern a symbol in a module without providing
1108;;; an initial binding for the corresponding variable. This is done
1109;;; with:
1110;;; (module-add! module symbol (make-undefined-variable))
1111;;;
1112;;; In that case, the symbol is interned in the module, but not
1113;;; bound there. The unbound symbol shadows any binding for that
1114;;; symbol that might otherwise be inherited from a member of the uses list.
1115;;;
1116
1117(define (module-obarray-get-handle ob key)
1118 ((if (symbol? key) hashq-get-handle hash-get-handle) ob key))
1119
1120(define (module-obarray-ref ob key)
1121 ((if (symbol? key) hashq-ref hash-ref) ob key))
1122
1123(define (module-obarray-set! ob key val)
1124 ((if (symbol? key) hashq-set! hash-set!) ob key val))
1125
1126(define (module-obarray-remove! ob key)
1127 ((if (symbol? key) hashq-remove! hash-remove!) ob key))
1128
1129;; module-symbol-locally-interned? module symbol
1130;;
1131;; is a symbol interned (not neccessarily defined) locally in a given module
1132;; or its uses? Interned symbols shadow inherited bindings even if
1133;; they are not themselves bound to a defined value.
1134;;
1135(define (module-symbol-locally-interned? m v)
1136 (not (not (module-obarray-get-handle (module-obarray m) v))))
1137
1138;; module-symbol-interned? module symbol
1139;;
1140;; is a symbol interned (not neccessarily defined) anywhere in a given module
1141;; or its uses? Interned symbols shadow inherited bindings even if
1142;; they are not themselves bound to a defined value.
1143;;
1144(define (module-symbol-interned? m v)
1145 (module-search module-symbol-locally-interned? m v))
1146
1147
1148;;; {Mapping modules x symbols --> variables}
1149;;;
1150
1151;; module-local-variable module symbol
1152;; return the local variable associated with a MODULE and SYMBOL.
1153;;
1154;;; This function is very important. It is the only function that can
1155;;; return a variable from a module other than the mutators that store
1156;;; new variables in modules. Therefore, this function is the location
1157;;; of the "lazy binder" hack.
1158;;;
1159;;; If symbol is defined in MODULE, and if the definition binds symbol
1160;;; to a variable, return that variable object.
1161;;;
1162;;; If the symbols is not found at first, but the module has a lazy binder,
1163;;; then try the binder.
1164;;;
1165;;; If the symbol is not found at all, return #f.
1166;;;
1167(define (module-local-variable m v)
6fa8995c
GH
1168; (caddr
1169; (list m v
0f2d19dd
JB
1170 (let ((b (module-obarray-ref (module-obarray m) v)))
1171 (or (and (variable? b) b)
1172 (and (module-binder m)
6fa8995c
GH
1173 ((module-binder m) m v #f)))))
1174;))
0f2d19dd
JB
1175
1176;; module-variable module symbol
1177;;
1178;; like module-local-variable, except search the uses in the
1179;; case V is not found in M.
1180;;
6906bd0d
MD
1181;; NOTE: This function is superseded with C code (see modules.c)
1182;;; when using the standard eval closure.
1183;;
0f2d19dd
JB
1184(define (module-variable m v)
1185 (module-search module-local-variable m v))
1186
1187
1188;;; {Mapping modules x symbols --> bindings}
1189;;;
1190;;; These are similar to the mapping to variables, except that the
1191;;; variable is dereferenced.
1192;;;
1193
1194;; module-symbol-binding module symbol opt-value
1195;;
1196;; return the binding of a variable specified by name within
1197;; a given module, signalling an error if the variable is unbound.
1198;; If the OPT-VALUE is passed, then instead of signalling an error,
1199;; return OPT-VALUE.
1200;;
1201(define (module-symbol-local-binding m v . opt-val)
1202 (let ((var (module-local-variable m v)))
1203 (if var
1204 (variable-ref var)
1205 (if (not (null? opt-val))
1206 (car opt-val)
1207 (error "Locally unbound variable." v)))))
1208
1209;; module-symbol-binding module symbol opt-value
1210;;
1211;; return the binding of a variable specified by name within
1212;; a given module, signalling an error if the variable is unbound.
1213;; If the OPT-VALUE is passed, then instead of signalling an error,
1214;; return OPT-VALUE.
1215;;
1216(define (module-symbol-binding m v . opt-val)
1217 (let ((var (module-variable m v)))
1218 (if var
1219 (variable-ref var)
1220 (if (not (null? opt-val))
1221 (car opt-val)
1222 (error "Unbound variable." v)))))
1223
1224
1225\f
1226;;; {Adding Variables to Modules}
1227;;;
1228;;;
1229
1230
1231;; module-make-local-var! module symbol
1232;;
1233;; ensure a variable for V in the local namespace of M.
1234;; If no variable was already there, then create a new and uninitialzied
1235;; variable.
1236;;
1237(define (module-make-local-var! m v)
1238 (or (let ((b (module-obarray-ref (module-obarray m) v)))
1777c18b
MD
1239 (and (variable? b)
1240 (begin
1a961d7e 1241 (module-modified m)
1777c18b 1242 b)))
0f2d19dd
JB
1243 (and (module-binder m)
1244 ((module-binder m) m v #t))
1245 (begin
1246 (let ((answer (make-undefined-variable v)))
1247 (module-obarray-set! (module-obarray m) v answer)
1a961d7e 1248 (module-modified m)
0f2d19dd
JB
1249 answer))))
1250
1251;; module-add! module symbol var
1252;;
1253;; ensure a particular variable for V in the local namespace of M.
1254;;
1255(define (module-add! m v var)
1256 (if (not (variable? var))
1257 (error "Bad variable to module-add!" var))
1777c18b 1258 (module-obarray-set! (module-obarray m) v var)
1a961d7e 1259 (module-modified m))
0f2d19dd
JB
1260
1261;; module-remove!
1262;;
1263;; make sure that a symbol is undefined in the local namespace of M.
1264;;
1265(define (module-remove! m v)
1777c18b 1266 (module-obarray-remove! (module-obarray m) v)
1a961d7e 1267 (module-modified m))
0f2d19dd
JB
1268
1269(define (module-clear! m)
1777c18b 1270 (vector-fill! (module-obarray m) '())
1a961d7e 1271 (module-modified m))
0f2d19dd
JB
1272
1273;; MODULE-FOR-EACH -- exported
1274;;
1275;; Call PROC on each symbol in MODULE, with arguments of (SYMBOL VARIABLE).
1276;;
1277(define (module-for-each proc module)
1278 (let ((obarray (module-obarray module)))
1279 (do ((index 0 (+ index 1))
1280 (end (vector-length obarray)))
1281 ((= index end))
1282 (for-each
1283 (lambda (bucket)
1284 (proc (car bucket) (cdr bucket)))
1285 (vector-ref obarray index)))))
1286
1287
1288(define (module-map proc module)
1289 (let* ((obarray (module-obarray module))
1290 (end (vector-length obarray)))
1291
1292 (let loop ((i 0)
1293 (answer '()))
1294 (if (= i end)
1295 answer
1296 (loop (+ 1 i)
1297 (append!
1298 (map (lambda (bucket)
1299 (proc (car bucket) (cdr bucket)))
1300 (vector-ref obarray i))
1301 answer))))))
1302\f
1303
1304;;; {Low Level Bootstrapping}
1305;;;
1306
1307;; make-root-module
1308
21ed9efe 1309;; A root module uses the symhash table (the system's privileged
0f2d19dd
JB
1310;; obarray). Being inside a root module is like using SCM without
1311;; any module system.
1312;;
1313
1314
31d50456 1315(define (root-module-closure m s define?)
17466330 1316 (let ((bi (builtin-variable s)))
0f2d19dd
JB
1317 (and bi
1318 (or define? (variable-bound? bi))
1319 (begin
1320 (module-add! m s bi)
1321 bi))))
1322
1323(define (make-root-module)
31d50456 1324 (make-module 1019 '() root-module-closure))
0f2d19dd
JB
1325
1326
1327;; make-scm-module
1328
1329;; An scm module is a module into which the lazy binder copies
1330;; variable bindings from the system symhash table. The mapping is
1331;; one way only; newly introduced bindings in an scm module are not
1332;; copied back into the system symhash table (and can be used to override
1333;; bindings from the symhash table).
1334;;
1335
6906bd0d 1336(define (scm-module-closure m s define?)
17466330 1337 (let ((bi (builtin-variable s)))
6906bd0d
MD
1338 (and bi
1339 (variable-bound? bi)
1340 (begin
1341 (module-add! m s bi)
1342 bi))))
0f2d19dd 1343
6906bd0d
MD
1344(define (make-scm-module)
1345 (make-module 1019 '() scm-module-closure))
0f2d19dd
JB
1346
1347
1348
1349;; the-module
631c1902
MD
1350;;
1351;; NOTE: This binding is used in libguile/modules.c.
1352;;
bd0fb3cf 1353(define the-module (make-fluid))
0f2d19dd 1354
7a0ff2f8 1355;; scm:eval-transformer
d43f8c97 1356;;
bd0fb3cf 1357;;(define scm:eval-transformer (make-fluid)) ; initialized in eval.c.
d43f8c97 1358
0f2d19dd
JB
1359;; set-current-module module
1360;;
1361;; set the current module as viewed by the normalizer.
1362;;
631c1902
MD
1363;; NOTE: This binding is used in libguile/modules.c.
1364;;
0f2d19dd 1365(define (set-current-module m)
bd0fb3cf 1366 (fluid-set! the-module m)
7a0ff2f8
MD
1367 (if m
1368 (begin
d7faeb2e 1369 ;; *top-level-lookup-closure* is now deprecated
bd0fb3cf
MD
1370 (fluid-set! *top-level-lookup-closure*
1371 (module-eval-closure (fluid-ref the-module)))
1372 (fluid-set! scm:eval-transformer (module-transformer (fluid-ref the-module))))
1373 (fluid-set! *top-level-lookup-closure* #f)))
0f2d19dd
JB
1374
1375
1376;; current-module
1377;;
1378;; return the current module as viewed by the normalizer.
1379;;
bd0fb3cf 1380(define (current-module) (fluid-ref the-module))
0f2d19dd
JB
1381\f
1382;;; {Module-based Loading}
1383;;;
1384
1385(define (save-module-excursion thunk)
1386 (let ((inner-module (current-module))
1387 (outer-module #f))
1388 (dynamic-wind (lambda ()
1389 (set! outer-module (current-module))
1390 (set-current-module inner-module)
1391 (set! inner-module #f))
1392 thunk
1393 (lambda ()
1394 (set! inner-module (current-module))
1395 (set-current-module outer-module)
1396 (set! outer-module #f)))))
1397
0f2d19dd
JB
1398(define basic-load load)
1399
c6775c40
MD
1400(define (load-module filename)
1401 (save-module-excursion
1402 (lambda ()
1403 (let ((oldname (and (current-load-port)
1404 (port-filename (current-load-port)))))
1405 (basic-load (if (and oldname
1406 (> (string-length filename) 0)
1407 (not (char=? (string-ref filename 0) #\/))
1408 (not (string=? (dirname oldname) ".")))
1409 (string-append (dirname oldname) "/" filename)
1410 filename))))))
0f2d19dd
JB
1411
1412
1413\f
44cf1f0f 1414;;; {MODULE-REF -- exported}
0f2d19dd
JB
1415;;
1416;; Returns the value of a variable called NAME in MODULE or any of its
1417;; used modules. If there is no such variable, then if the optional third
1418;; argument DEFAULT is present, it is returned; otherwise an error is signaled.
1419;;
1420(define (module-ref module name . rest)
1421 (let ((variable (module-variable module name)))
1422 (if (and variable (variable-bound? variable))
1423 (variable-ref variable)
1424 (if (null? rest)
1425 (error "No variable named" name 'in module)
1426 (car rest) ; default value
1427 ))))
1428
1429;; MODULE-SET! -- exported
1430;;
1431;; Sets the variable called NAME in MODULE (or in a module that MODULE uses)
1432;; to VALUE; if there is no such variable, an error is signaled.
1433;;
1434(define (module-set! module name value)
1435 (let ((variable (module-variable module name)))
1436 (if variable
1437 (variable-set! variable value)
1438 (error "No variable named" name 'in module))))
1439
1440;; MODULE-DEFINE! -- exported
1441;;
1442;; Sets the variable called NAME in MODULE to VALUE; if there is no such
1443;; variable, it is added first.
1444;;
1445(define (module-define! module name value)
1446 (let ((variable (module-local-variable module name)))
1447 (if variable
1777c18b
MD
1448 (begin
1449 (variable-set! variable value)
1a961d7e 1450 (module-modified module))
0f2d19dd
JB
1451 (module-add! module name (make-variable value name)))))
1452
ed218d98
MV
1453;; MODULE-DEFINED? -- exported
1454;;
1455;; Return #t iff NAME is defined in MODULE (or in a module that MODULE
1456;; uses)
1457;;
1458(define (module-defined? module name)
1459 (let ((variable (module-variable module name)))
1460 (and variable (variable-bound? variable))))
1461
0f2d19dd
JB
1462;; MODULE-USE! module interface
1463;;
1464;; Add INTERFACE to the list of interfaces used by MODULE.
1465;;
1466(define (module-use! module interface)
1467 (set-module-uses! module
1777c18b 1468 (cons interface (delq! interface (module-uses module))))
1a961d7e 1469 (module-modified module))
0f2d19dd
JB
1470
1471\f
0f2d19dd
JB
1472;;; {Recursive Namespaces}
1473;;;
1474;;;
1475;;; A hierarchical namespace emerges if we consider some module to be
1476;;; root, and variables bound to modules as nested namespaces.
1477;;;
1478;;; The routines in this file manage variable names in hierarchical namespace.
1479;;; Each variable name is a list of elements, looked up in successively nested
1480;;; modules.
1481;;;
0dd5491c 1482;;; (nested-ref some-root-module '(foo bar baz))
0f2d19dd
JB
1483;;; => <value of a variable named baz in the module bound to bar in
1484;;; the module bound to foo in some-root-module>
1485;;;
1486;;;
1487;;; There are:
1488;;;
1489;;; ;; a-root is a module
1490;;; ;; name is a list of symbols
1491;;;
0dd5491c
MD
1492;;; nested-ref a-root name
1493;;; nested-set! a-root name val
1494;;; nested-define! a-root name val
1495;;; nested-remove! a-root name
0f2d19dd
JB
1496;;;
1497;;;
1498;;; (current-module) is a natural choice for a-root so for convenience there are
1499;;; also:
1500;;;
0dd5491c
MD
1501;;; local-ref name == nested-ref (current-module) name
1502;;; local-set! name val == nested-set! (current-module) name val
1503;;; local-define! name val == nested-define! (current-module) name val
1504;;; local-remove! name == nested-remove! (current-module) name
0f2d19dd
JB
1505;;;
1506
1507
0dd5491c 1508(define (nested-ref root names)
0f2d19dd
JB
1509 (let loop ((cur root)
1510 (elts names))
1511 (cond
1512 ((null? elts) cur)
1513 ((not (module? cur)) #f)
1514 (else (loop (module-ref cur (car elts) #f) (cdr elts))))))
1515
0dd5491c 1516(define (nested-set! root names val)
0f2d19dd
JB
1517 (let loop ((cur root)
1518 (elts names))
1519 (if (null? (cdr elts))
1520 (module-set! cur (car elts) val)
1521 (loop (module-ref cur (car elts)) (cdr elts)))))
1522
0dd5491c 1523(define (nested-define! root names val)
0f2d19dd
JB
1524 (let loop ((cur root)
1525 (elts names))
1526 (if (null? (cdr elts))
1527 (module-define! cur (car elts) val)
1528 (loop (module-ref cur (car elts)) (cdr elts)))))
1529
0dd5491c 1530(define (nested-remove! root names)
0f2d19dd
JB
1531 (let loop ((cur root)
1532 (elts names))
1533 (if (null? (cdr elts))
1534 (module-remove! cur (car elts))
1535 (loop (module-ref cur (car elts)) (cdr elts)))))
1536
0dd5491c
MD
1537(define (local-ref names) (nested-ref (current-module) names))
1538(define (local-set! names val) (nested-set! (current-module) names val))
1539(define (local-define names val) (nested-define! (current-module) names val))
1540(define (local-remove names) (nested-remove! (current-module) names))
0f2d19dd
JB
1541
1542
1543\f
8bb7330c 1544;;; {The (app) module}
0f2d19dd
JB
1545;;;
1546;;; The root of conventionally named objects not directly in the top level.
1547;;;
8bb7330c
JB
1548;;; (app modules)
1549;;; (app modules guile)
0f2d19dd
JB
1550;;;
1551;;; The directory of all modules and the standard root module.
1552;;;
1553
edc185c7
MD
1554(define (module-public-interface m)
1555 (module-ref m '%module-public-interface #f))
1556(define (set-module-public-interface! m i)
1557 (module-define! m '%module-public-interface i))
1558(define (set-system-module! m s)
1559 (set-procedure-property! (module-eval-closure m) 'system-module s))
0f2d19dd
JB
1560(define the-root-module (make-root-module))
1561(define the-scm-module (make-scm-module))
1562(set-module-public-interface! the-root-module the-scm-module)
d5504515
MD
1563(set-module-name! the-root-module '(guile))
1564(set-module-name! the-scm-module '(guile))
1565(set-module-kind! the-scm-module 'interface)
edc185c7 1566(for-each set-system-module! (list the-root-module the-scm-module) '(#t #t))
0f2d19dd
JB
1567
1568(set-current-module the-root-module)
1569
1570(define app (make-module 31))
0dd5491c
MD
1571(local-define '(app modules) (make-module 31))
1572(local-define '(app modules guile) the-root-module)
0f2d19dd
JB
1573
1574;; (define-special-value '(app modules new-ws) (lambda () (make-scm-module)))
1575
432558b9
MD
1576(define (try-load-module name)
1577 (or (try-module-linked name)
1578 (try-module-autoload name)
1579 (try-module-dynamic-link name)))
1580
1f60d9d2
MD
1581;; NOTE: This binding is used in libguile/modules.c.
1582;;
0209ca9a 1583(define (resolve-module name . maybe-autoload)
0f2d19dd 1584 (let ((full-name (append '(app modules) name)))
0dd5491c 1585 (let ((already (local-ref full-name)))
432558b9
MD
1586 (if already
1587 ;; The module already exists...
1588 (if (and (or (null? maybe-autoload) (car maybe-autoload))
1589 (not (module-ref already '%module-public-interface #f)))
1590 ;; ...but we are told to load and it doesn't contain source, so
1591 (begin
1592 (try-load-module name)
1593 already)
1594 ;; simply return it.
1595 already)
3e3cec45 1596 (begin
432558b9 1597 ;; Try to autoload it if we are told so
3e3cec45 1598 (if (or (null? maybe-autoload) (car maybe-autoload))
432558b9
MD
1599 (try-load-module name))
1600 ;; Get/create it.
3e3cec45 1601 (make-modules-in (current-module) full-name))))))
0f2d19dd
JB
1602
1603(define (beautify-user-module! module)
3e3cec45
MD
1604 (let ((interface (module-public-interface module)))
1605 (if (or (not interface)
1606 (eq? interface module))
1607 (let ((interface (make-module 31)))
1608 (set-module-name! interface (module-name module))
1609 (set-module-kind! interface 'interface)
1610 (set-module-public-interface! module interface))))
cc7f066c
MD
1611 (if (and (not (memq the-scm-module (module-uses module)))
1612 (not (eq? module the-root-module)))
0f2d19dd
JB
1613 (set-module-uses! module (append (module-uses module) (list the-scm-module)))))
1614
90847923
MD
1615(define (purify-module! module)
1616 "Removes bindings in MODULE which are inherited from the (guile) module."
1617 (let ((use-list (module-uses module)))
1618 (if (and (pair? use-list)
1619 (eq? (car (last-pair use-list)) the-scm-module))
1620 (set-module-uses! module (reverse (cdr (reverse use-list)))))))
1621
631c1902
MD
1622;; NOTE: This binding is used in libguile/modules.c.
1623;;
0f2d19dd
JB
1624(define (make-modules-in module name)
1625 (if (null? name)
1626 module
1627 (cond
3e3cec45
MD
1628 ((module-ref module (car name) #f)
1629 => (lambda (m) (make-modules-in m (cdr name))))
0f2d19dd
JB
1630 (else (let ((m (make-module 31)))
1631 (set-module-kind! m 'directory)
d5504515
MD
1632 (set-module-name! m (append (or (module-name module)
1633 '())
1634 (list (car name))))
0f2d19dd
JB
1635 (module-define! module (car name) m)
1636 (make-modules-in m (cdr name)))))))
1637
1638(define (resolve-interface name)
1639 (let ((module (resolve-module name)))
1640 (and module (module-public-interface module))))
1641
1642
1643(define %autoloader-developer-mode #t)
1644
1645(define (process-define-module args)
1646 (let* ((module-id (car args))
0209ca9a 1647 (module (resolve-module module-id #f))
0f2d19dd
JB
1648 (kws (cdr args)))
1649 (beautify-user-module! module)
0209ca9a 1650 (let loop ((kws kws)
44484f52
MD
1651 (reversed-interfaces '())
1652 (exports '()))
0209ca9a 1653 (if (null? kws)
44484f52
MD
1654 (begin
1655 (for-each (lambda (interface)
1656 (module-use! module interface))
1657 reversed-interfaces)
1658 (module-export! module exports))
06f0414c
MD
1659 (let ((keyword (if (keyword? (car kws))
1660 (keyword->symbol (car kws))
1661 (and (symbol? (car kws))
1662 (let ((s (symbol->string (car kws))))
1663 (and (eq? (string-ref s 0) #\:)
1664 (string->symbol (substring s 1))))))))
f714ca8e
MD
1665 (case keyword
1666 ((use-module use-syntax)
1667 (if (not (pair? (cdr kws)))
1668 (error "unrecognized defmodule argument" kws))
1669 (let* ((used-name (cadr kws))
1670 (used-module (resolve-module used-name)))
45a02a29
MD
1671 (if (not (module-ref used-module
1672 '%module-public-interface
1673 #f))
3e3cec45 1674 (begin
45a02a29
MD
1675 ((if %autoloader-developer-mode warn error)
1676 "no code for module" (module-name used-module))
1677 (beautify-user-module! used-module)))
1678 (let ((interface (module-public-interface used-module)))
1679 (if (not interface)
1680 (error "missing interface for use-module"
1681 used-module))
1682 (if (eq? keyword 'use-syntax)
7cbaee0c
MD
1683 (set-module-transformer!
1684 module
45a02a29
MD
1685 (module-ref interface (car (last-pair used-name))
1686 #f)))
1687 (loop (cddr kws)
44484f52
MD
1688 (cons interface reversed-interfaces)
1689 exports))))
71225060
MD
1690 ((autoload)
1691 (if (not (and (pair? (cdr kws)) (pair? (cddr kws))))
1692 (error "unrecognized defmodule argument" kws))
1693 (loop (cdddr kws)
1694 (cons (make-autoload-interface module
1695 (cadr kws)
1696 (caddr kws))
44484f52
MD
1697 reversed-interfaces)
1698 exports))
edc185c7
MD
1699 ((no-backtrace)
1700 (set-system-module! module #t)
44484f52 1701 (loop (cdr kws) reversed-interfaces exports))
90847923
MD
1702 ((pure)
1703 (purify-module! module)
44484f52 1704 (loop (cdr kws) reversed-interfaces exports))
90847923 1705 ((export)
a473fead 1706 (if (not (pair? (cdr kws)))
90847923 1707 (error "unrecognized defmodule argument" kws))
44484f52
MD
1708 (loop (cddr kws)
1709 reversed-interfaces
1710 (append (cadr kws) exports)))
f714ca8e
MD
1711 (else
1712 (error "unrecognized defmodule argument" kws))))))
645e38d9 1713 (set-current-module module)
0f2d19dd 1714 module))
71225060
MD
1715
1716;;; {Autoload}
1717
1718(define (make-autoload-interface module name bindings)
1719 (let ((b (lambda (a sym definep)
1720 (and (memq sym bindings)
1721 (let ((i (module-public-interface (resolve-module name))))
1722 (if (not i)
1723 (error "missing interface for module" name))
1724 ;; Replace autoload-interface with interface
1725 (set-car! (memq a (module-uses module)) i)
1726 (module-local-variable i sym))))))
d5504515 1727 (module-constructor #() '() b #f #f name 'autoload
6b64c19b 1728 '() (make-weak-value-hash-table 31) 0)))
71225060 1729
0f2d19dd 1730\f
44cf1f0f 1731;;; {Autoloading modules}
0f2d19dd
JB
1732
1733(define autoloads-in-progress '())
1734
1735(define (try-module-autoload module-name)
0f2d19dd 1736 (let* ((reverse-name (reverse module-name))
06f0414c 1737 (name (symbol->string (car reverse-name)))
0f2d19dd 1738 (dir-hint-module-name (reverse (cdr reverse-name)))
06f0414c
MD
1739 (dir-hint (apply string-append
1740 (map (lambda (elt)
1741 (string-append (symbol->string elt) "/"))
1742 dir-hint-module-name))))
0209ca9a 1743 (resolve-module dir-hint-module-name #f)
0f2d19dd
JB
1744 (and (not (autoload-done-or-in-progress? dir-hint name))
1745 (let ((didit #f))
1746 (dynamic-wind
1747 (lambda () (autoload-in-progress! dir-hint name))
defed517
MD
1748 (lambda ()
1749 (let ((full (%search-load-path (in-vicinity dir-hint name))))
1750 (if full
1751 (begin
1752 (save-module-excursion (lambda () (primitive-load full)))
1753 (set! didit #t)))))
0f2d19dd
JB
1754 (lambda () (set-autoloaded! dir-hint name didit)))
1755 didit))))
1756
71225060 1757\f
d0cbd20c
MV
1758;;; Dynamic linking of modules
1759
1760;; Initializing a module that is written in C is a two step process.
1761;; First the module's `module init' function is called. This function
1762;; is expected to call `scm_register_module_xxx' to register the `real
1763;; init' function. Later, when the module is referenced for the first
1764;; time, this real init function is called in the right context. See
1765;; gtcltk-lib/gtcltk-module.c for an example.
1766;;
1767;; The code for the module can be in a regular shared library (so that
1768;; the `module init' function will be called when libguile is
1769;; initialized). Or it can be dynamically linked.
1770;;
1771;; You can safely call `scm_register_module_xxx' before libguile
1772;; itself is initialized. You could call it from an C++ constructor
1773;; of a static object, for example.
1774;;
1775;; To make your Guile extension into a dynamic linkable module, follow
1776;; these easy steps:
1777;;
8bb7330c 1778;; - Find a name for your module, like (ice-9 gtcltk)
d0cbd20c
MV
1779;; - Write a function with a name like
1780;;
1781;; scm_init_ice_9_gtcltk_module
1782;;
1783;; This is your `module init' function. It should call
1784;;
1785;; scm_register_module_xxx ("ice-9 gtcltk", scm_init_gtcltk);
1786;;
1787;; "ice-9 gtcltk" is the C version of the module name. Slashes are
1788;; replaced by spaces, the rest is untouched. `scm_init_gtcltk' is
ed218d98 1789;; the real init function that executes the usual initializations
d0cbd20c
MV
1790;; like making new smobs, etc.
1791;;
1792;; - Make a shared library with your code and a name like
1793;;
1794;; ice-9/libgtcltk.so
1795;;
1796;; and put it somewhere in %load-path.
1797;;
8bb7330c 1798;; - Then you can simply write `:use-module (ice-9 gtcltk)' and it
d0cbd20c
MV
1799;; will be linked automatically.
1800;;
1801;; This is all very experimental.
1802
1803(define (split-c-module-name str)
1804 (let loop ((rev '())
1805 (start 0)
1806 (pos 0)
1807 (end (string-length str)))
1808 (cond
1809 ((= pos end)
1810 (reverse (cons (string->symbol (substring str start pos)) rev)))
1811 ((eq? (string-ref str pos) #\space)
1812 (loop (cons (string->symbol (substring str start pos)) rev)
1813 (+ pos 1)
1814 (+ pos 1)
1815 end))
1816 (else
1817 (loop rev start (+ pos 1) end)))))
1818
1819(define (convert-c-registered-modules dynobj)
1820 (let ((res (map (lambda (c)
1821 (list (split-c-module-name (car c)) (cdr c) dynobj))
1822 (c-registered-modules))))
1823 (c-clear-registered-modules)
1824 res))
1825
3e3cec45
MD
1826(define registered-modules '())
1827
1828(define (register-modules dynobj)
1829 (set! registered-modules
1830 (append! (convert-c-registered-modules dynobj)
1831 registered-modules)))
1832
a4e7b79a
MV
1833(define (warn-autoload-deprecation modname)
1834 (display
1835 ";;; Autoloading of compiled code modules is deprecated.\n"
1836 (current-error-port))
1837 (display
1838 ";;; Write a Scheme file instead that uses `dynamic-link' directly.\n"
1839 (current-error-port))
1840 (format (current-error-port)
64143414 1841 ";;; (You just tried to autoload module ~S.)\n" modname))
a4e7b79a 1842
d0cbd20c 1843(define (init-dynamic-module modname)
3e3cec45
MD
1844 ;; Register any linked modules which has been registered on the C level
1845 (register-modules #f)
d0cbd20c
MV
1846 (or-map (lambda (modinfo)
1847 (if (equal? (car modinfo) modname)
c04e89c7 1848 (begin
999010b6 1849 (warn-autoload-deprecation modname)
c04e89c7
MD
1850 (set! registered-modules (delq! modinfo registered-modules))
1851 (let ((mod (resolve-module modname #f)))
1852 (save-module-excursion
1853 (lambda ()
1854 (set-current-module mod)
1855 (set-module-public-interface! mod mod)
1856 (dynamic-call (cadr modinfo) (caddr modinfo))
1857 ))
1858 #t))
d0cbd20c
MV
1859 #f))
1860 registered-modules))
1861
1862(define (dynamic-maybe-call name dynobj)
1863 (catch #t ; could use false-if-exception here
1864 (lambda ()
1865 (dynamic-call name dynobj))
1866 (lambda args
1867 #f)))
1868
ed218d98
MV
1869(define (dynamic-maybe-link filename)
1870 (catch #t ; could use false-if-exception here
1871 (lambda ()
1872 (dynamic-link filename))
1873 (lambda args
1874 #f)))
1875
d0cbd20c
MV
1876(define (find-and-link-dynamic-module module-name)
1877 (define (make-init-name mod-name)
bd9e24b3 1878 (string-append "scm_init"
d0cbd20c
MV
1879 (list->string (map (lambda (c)
1880 (if (or (char-alphabetic? c)
1881 (char-numeric? c))
1882 c
1883 #\_))
1884 (string->list mod-name)))
bd9e24b3 1885 "_module"))
ebd79f62
TP
1886
1887 ;; Put the subdirectory for this module in the car of SUBDIR-AND-LIBNAME,
1888 ;; and the `libname' (the name of the module prepended by `lib') in the cdr
1889 ;; field. For example, if MODULE-NAME is the list (inet tcp-ip udp), then
1890 ;; SUBDIR-AND-LIBNAME will be the pair ("inet/tcp-ip" . "libudp").
1891 (let ((subdir-and-libname
d0cbd20c
MV
1892 (let loop ((dirs "")
1893 (syms module-name))
ebd79f62 1894 (if (null? (cdr syms))
06f0414c
MD
1895 (cons dirs (string-append "lib" (symbol->string (car syms))))
1896 (loop (string-append dirs (symbol->string (car syms)) "/")
1897 (cdr syms)))))
d0cbd20c
MV
1898 (init (make-init-name (apply string-append
1899 (map (lambda (s)
06f0414c
MD
1900 (string-append "_"
1901 (symbol->string s)))
d0cbd20c 1902 module-name)))))
ebd79f62
TP
1903 (let ((subdir (car subdir-and-libname))
1904 (libname (cdr subdir-and-libname)))
1905
1906 ;; Now look in each dir in %LOAD-PATH for `subdir/libfoo.la'. If that
1907 ;; file exists, fetch the dlname from that file and attempt to link
1908 ;; against it. If `subdir/libfoo.la' does not exist, or does not seem
1909 ;; to name any shared library, look for `subdir/libfoo.so' instead and
1910 ;; link against that.
1911 (let check-dirs ((dir-list %load-path))
1912 (if (null? dir-list)
1913 #f
1914 (let* ((dir (in-vicinity (car dir-list) subdir))
1915 (sharlib-full
1916 (or (try-using-libtool-name dir libname)
1917 (try-using-sharlib-name dir libname))))
1918 (if (and sharlib-full (file-exists? sharlib-full))
1919 (link-dynamic-module sharlib-full init)
1920 (check-dirs (cdr dir-list)))))))))
1921
1922(define (try-using-libtool-name libdir libname)
ebd79f62
TP
1923 (let ((libtool-filename (in-vicinity libdir
1924 (string-append libname ".la"))))
1925 (and (file-exists? libtool-filename)
352d134c 1926 libtool-filename)))
ebd79f62
TP
1927
1928(define (try-using-sharlib-name libdir libname)
1929 (in-vicinity libdir (string-append libname ".so")))
d0cbd20c
MV
1930
1931(define (link-dynamic-module filename initname)
3e3cec45
MD
1932 ;; Register any linked modules which has been registered on the C level
1933 (register-modules #f)
6b856182
MV
1934 (let ((dynobj (dynamic-link filename)))
1935 (dynamic-call initname dynobj)
3e3cec45 1936 (register-modules dynobj)))
a4f9b1f6
MD
1937
1938(define (try-module-linked module-name)
1939 (init-dynamic-module module-name))
1940
d0cbd20c 1941(define (try-module-dynamic-link module-name)
a4f9b1f6
MD
1942 (and (find-and-link-dynamic-module module-name)
1943 (init-dynamic-module module-name)))
d0cbd20c 1944
ed218d98
MV
1945
1946
0f2d19dd
JB
1947(define autoloads-done '((guile . guile)))
1948
1949(define (autoload-done-or-in-progress? p m)
1950 (let ((n (cons p m)))
1951 (->bool (or (member n autoloads-done)
1952 (member n autoloads-in-progress)))))
1953
1954(define (autoload-done! p m)
1955 (let ((n (cons p m)))
1956 (set! autoloads-in-progress
1957 (delete! n autoloads-in-progress))
1958 (or (member n autoloads-done)
1959 (set! autoloads-done (cons n autoloads-done)))))
1960
1961(define (autoload-in-progress! p m)
1962 (let ((n (cons p m)))
1963 (set! autoloads-done
1964 (delete! n autoloads-done))
1965 (set! autoloads-in-progress (cons n autoloads-in-progress))))
1966
1967(define (set-autoloaded! p m done?)
1968 (if done?
1969 (autoload-done! p m)
1970 (let ((n (cons p m)))
1971 (set! autoloads-done (delete! n autoloads-done))
1972 (set! autoloads-in-progress (delete! n autoloads-in-progress)))))
1973
1974
1975
a54e6fa3
KN
1976\f
1977;; {EVAL-CASE}
1978;;
1979;; (eval-case ((situation*) forms)* (else forms)?)
1980;;
1981;; Evaluate certain code based on the situation that eval-case is used
1982;; in. The only defined situation right now is `load-toplevel' which
1983;; triggers for code evaluated at the top-level, for example from the
1984;; REPL or when loading a file.
1985
1986(define eval-case
1987 (procedure->memoizing-macro
1988 (lambda (exp env)
1989 (define (toplevel-env? env)
1990 (or (not (pair? env)) (not (pair? (car env)))))
1991 (define (syntax)
1992 (error "syntax error in eval-case"))
1993 (let loop ((clauses (cdr exp)))
1994 (cond
1995 ((null? clauses)
1996 #f)
1997 ((not (list? (car clauses)))
1998 (syntax))
1999 ((eq? 'else (caar clauses))
2000 (or (null? (cdr clauses))
2001 (syntax))
2002 (cons 'begin (cdar clauses)))
2003 ((not (list? (caar clauses)))
2004 (syntax))
2005 ((and (toplevel-env? env)
2006 (memq 'load-toplevel (caar clauses)))
2007 (cons 'begin (cdar clauses)))
2008 (else
2009 (loop (cdr clauses))))))))
0f2d19dd
JB
2010
2011\f
2012;;; {Macros}
2013;;;
2014
7a0ff2f8
MD
2015(define (primitive-macro? m)
2016 (and (macro? m)
2017 (not (macro-transformer m))))
2018
2019;;; {Defmacros}
2020;;;
9591db87
MD
2021(define macro-table (make-weak-key-hash-table 523))
2022(define xformer-table (make-weak-key-hash-table 523))
0f2d19dd
JB
2023
2024(define (defmacro? m) (hashq-ref macro-table m))
2025(define (assert-defmacro?! m) (hashq-set! macro-table m #t))
2026(define (defmacro-transformer m) (hashq-ref xformer-table m))
2027(define (set-defmacro-transformer! m t) (hashq-set! xformer-table m t))
2028
2029(define defmacro:transformer
2030 (lambda (f)
2031 (let* ((xform (lambda (exp env)
2032 (copy-tree (apply f (cdr exp)))))
2033 (a (procedure->memoizing-macro xform)))
2034 (assert-defmacro?! a)
2035 (set-defmacro-transformer! a f)
2036 a)))
2037
2038
2039(define defmacro
2040 (let ((defmacro-transformer
2041 (lambda (name parms . body)
2042 (let ((transformer `(lambda ,parms ,@body)))
8add1522
KN
2043 `(eval-case
2044 ((load-toplevel)
2045 (define ,name (defmacro:transformer ,transformer)))
2046 (else
2047 (error "defmacro can only be used at the top level")))))))
0f2d19dd
JB
2048 (defmacro:transformer defmacro-transformer)))
2049
2050(define defmacro:syntax-transformer
2051 (lambda (f)
2052 (procedure->syntax
2053 (lambda (exp env)
2054 (copy-tree (apply f (cdr exp)))))))
2055
ed218d98
MV
2056
2057;; XXX - should the definition of the car really be looked up in the
2058;; current module?
2059
0f2d19dd
JB
2060(define (macroexpand-1 e)
2061 (cond
2062 ((pair? e) (let* ((a (car e))
ed218d98 2063 (val (and (symbol? a) (local-ref (list a)))))
0f2d19dd
JB
2064 (if (defmacro? val)
2065 (apply (defmacro-transformer val) (cdr e))
2066 e)))
2067 (#t e)))
2068
2069(define (macroexpand e)
2070 (cond
2071 ((pair? e) (let* ((a (car e))
ed218d98 2072 (val (and (symbol? a) (local-ref (list a)))))
0f2d19dd
JB
2073 (if (defmacro? val)
2074 (macroexpand (apply (defmacro-transformer val) (cdr e)))
2075 e)))
2076 (#t e)))
2077
534a0099 2078(provide 'defmacro)
0f2d19dd
JB
2079
2080\f
2081
83b38198
MD
2082;;; {Run-time options}
2083
e9bab9df
DH
2084(define define-option-interface
2085 (let* ((option-name car)
2086 (option-value cadr)
2087 (option-documentation caddr)
2088
2089 (print-option (lambda (option)
2090 (display (option-name option))
2091 (if (< (string-length
2092 (symbol->string (option-name option)))
2093 8)
2094 (display #\tab))
2095 (display #\tab)
2096 (display (option-value option))
2097 (display #\tab)
2098 (display (option-documentation option))
2099 (newline)))
2100
2101 ;; Below follow the macros defining the run-time option interfaces.
2102
2103 (make-options (lambda (interface)
2104 `(lambda args
2105 (cond ((null? args) (,interface))
2106 ((list? (car args))
2107 (,interface (car args)) (,interface))
2108 (else (for-each ,print-option
2109 (,interface #t)))))))
2110
2111 (make-enable (lambda (interface)
83b38198 2112 `(lambda flags
e9bab9df
DH
2113 (,interface (append flags (,interface)))
2114 (,interface))))
2115
2116 (make-disable (lambda (interface)
2117 `(lambda flags
2118 (let ((options (,interface)))
2119 (for-each (lambda (flag)
2120 (set! options (delq! flag options)))
2121 flags)
2122 (,interface options)
2123 (,interface)))))
2124
2125 (make-set! (lambda (interface)
2126 `((name exp)
2127 (,'quasiquote
2128 (begin (,interface (append (,interface)
2129 (list '(,'unquote name)
2130 (,'unquote exp))))
2131 (,interface)))))))
2132 (procedure->macro
83b38198
MD
2133 (lambda (exp env)
2134 (cons 'begin
e9bab9df
DH
2135 (let* ((option-group (cadr exp))
2136 (interface (car option-group)))
2137 (append (map (lambda (name constructor)
2138 `(define ,name
2139 ,(constructor interface)))
2140 (cadr option-group)
2141 (list make-options
2142 make-enable
2143 make-disable))
2144 (map (lambda (name constructor)
2145 `(defmacro ,name
2146 ,@(constructor interface)))
2147 (caddr option-group)
2148 (list make-set!)))))))))
2149
2150(define-option-interface
2151 (eval-options-interface
2152 (eval-options eval-enable eval-disable)
2153 (eval-set!)))
2154
2155(define-option-interface
2156 (debug-options-interface
2157 (debug-options debug-enable debug-disable)
2158 (debug-set!)))
2159
2160(define-option-interface
2161 (evaluator-traps-interface
2162 (traps trap-enable trap-disable)
2163 (trap-set!)))
2164
2165(define-option-interface
2166 (read-options-interface
2167 (read-options read-enable read-disable)
2168 (read-set!)))
2169
2170(define-option-interface
2171 (print-options-interface
2172 (print-options print-enable print-disable)
2173 (print-set!)))
83b38198
MD
2174
2175\f
2176
0f2d19dd
JB
2177;;; {Running Repls}
2178;;;
2179
2180(define (repl read evaler print)
75a97b92 2181 (let loop ((source (read (current-input-port))))
0f2d19dd 2182 (print (evaler source))
75a97b92 2183 (loop (read (current-input-port)))))
0f2d19dd
JB
2184
2185;; A provisional repl that acts like the SCM repl:
2186;;
2187(define scm-repl-silent #f)
2188(define (assert-repl-silence v) (set! scm-repl-silent v))
2189
21ed9efe
MD
2190(define *unspecified* (if #f #f))
2191(define (unspecified? v) (eq? v *unspecified*))
2192
2193(define scm-repl-print-unspecified #f)
2194(define (assert-repl-print-unspecified v) (set! scm-repl-print-unspecified v))
2195
79451588 2196(define scm-repl-verbose #f)
0f2d19dd
JB
2197(define (assert-repl-verbosity v) (set! scm-repl-verbose v))
2198
e6875011 2199(define scm-repl-prompt "guile> ")
0f2d19dd 2200
e6875011
MD
2201(define (set-repl-prompt! v) (set! scm-repl-prompt v))
2202
d5d34fa1
MD
2203(define (default-lazy-handler key . args)
2204 (save-stack lazy-handler-dispatch)
2205 (apply throw key args))
2206
45456413 2207(define enter-frame-handler default-lazy-handler)
d5d34fa1
MD
2208(define apply-frame-handler default-lazy-handler)
2209(define exit-frame-handler default-lazy-handler)
2210
2211(define (lazy-handler-dispatch key . args)
2212 (case key
2213 ((apply-frame)
2214 (apply apply-frame-handler key args))
2215 ((exit-frame)
2216 (apply exit-frame-handler key args))
45456413
MD
2217 ((enter-frame)
2218 (apply enter-frame-handler key args))
d5d34fa1
MD
2219 (else
2220 (apply default-lazy-handler key args))))
0f2d19dd 2221
3e3cec45 2222(define abort-hook (make-hook))
59e1116d 2223
28d8ab3c
GH
2224;; these definitions are used if running a script.
2225;; otherwise redefined in error-catching-loop.
2226(define (set-batch-mode?! arg) #t)
2227(define (batch-mode?) #t)
4bbbcd5c 2228
0f2d19dd 2229(define (error-catching-loop thunk)
4bbbcd5c
GH
2230 (let ((status #f)
2231 (interactive #t))
8e44e7a0
GH
2232 (define (loop first)
2233 (let ((next
2234 (catch #t
9a0d70e2 2235
8e44e7a0
GH
2236 (lambda ()
2237 (lazy-catch #t
2238 (lambda ()
2239 (dynamic-wind
2240 (lambda () (unmask-signals))
2241 (lambda ()
45456413
MD
2242 (with-traps
2243 (lambda ()
2244 (first)
8e44e7a0 2245
45456413
MD
2246 ;; This line is needed because mark
2247 ;; doesn't do closures quite right.
2248 ;; Unreferenced locals should be
2249 ;; collected.
2250 ;;
2251 (set! first #f)
2252 (let loop ((v (thunk)))
2253 (loop (thunk)))
2254 #f)))
8e44e7a0
GH
2255 (lambda () (mask-signals))))
2256
2257 lazy-handler-dispatch))
2258
2259 (lambda (key . args)
2260 (case key
2261 ((quit)
8e44e7a0
GH
2262 (set! status args)
2263 #f)
2264
2265 ((switch-repl)
2266 (apply throw 'switch-repl args))
2267
2268 ((abort)
2269 ;; This is one of the closures that require
2270 ;; (set! first #f) above
2271 ;;
2272 (lambda ()
04efd24d 2273 (run-hook abort-hook)
e13c54c4 2274 (force-output (current-output-port))
8e44e7a0
GH
2275 (display "ABORT: " (current-error-port))
2276 (write args (current-error-port))
2277 (newline (current-error-port))
4bbbcd5c 2278 (if interactive
e13c54c4
JB
2279 (begin
2280 (if (and
2281 (not has-shown-debugger-hint?)
2282 (not (memq 'backtrace
2283 (debug-options-interface)))
2284 (stack? (fluid-ref the-last-stack)))
2285 (begin
2286 (newline (current-error-port))
2287 (display
cb546c61 2288 "Type \"(backtrace)\" to get more information or \"(debug)\" to enter the debugger.\n"
e13c54c4
JB
2289 (current-error-port))
2290 (set! has-shown-debugger-hint? #t)))
2291 (force-output (current-error-port)))
2292 (begin
2293 (primitive-exit 1)))
8e44e7a0
GH
2294 (set! stack-saved? #f)))
2295
2296 (else
2297 ;; This is the other cons-leak closure...
2298 (lambda ()
2299 (cond ((= (length args) 4)
2300 (apply handle-system-error key args))
2301 (else
2302 (apply bad-throw key args))))))))))
2303 (if next (loop next) status)))
5f5f2642
MD
2304 (set! set-batch-mode?! (lambda (arg)
2305 (cond (arg
2306 (set! interactive #f)
2307 (restore-signals))
2308 (#t
2309 (error "sorry, not implemented")))))
2310 (set! batch-mode? (lambda () (not interactive)))
8e44e7a0 2311 (loop (lambda () #t))))
0f2d19dd 2312
8bb7f646 2313;;(define the-last-stack (make-fluid)) Defined by scm_init_backtrace ()
8087b6be 2314(define before-signal-stack (make-fluid))
21ed9efe
MD
2315(define stack-saved? #f)
2316
2317(define (save-stack . narrowing)
edc185c7
MD
2318 (or stack-saved?
2319 (cond ((not (memq 'debug (debug-options-interface)))
2320 (fluid-set! the-last-stack #f)
2321 (set! stack-saved? #t))
2322 (else
2323 (fluid-set!
2324 the-last-stack
2325 (case (stack-id #t)
2326 ((repl-stack)
704f4e86 2327 (apply make-stack #t save-stack primitive-eval #t 0 narrowing))
edc185c7
MD
2328 ((load-stack)
2329 (apply make-stack #t save-stack 0 #t 0 narrowing))
2330 ((tk-stack)
2331 (apply make-stack #t save-stack tk-stack-mark #t 0 narrowing))
2332 ((#t)
2333 (apply make-stack #t save-stack 0 1 narrowing))
2334 (else
2335 (let ((id (stack-id #t)))
2336 (and (procedure? id)
2337 (apply make-stack #t save-stack id #t 0 narrowing))))))
2338 (set! stack-saved? #t)))))
1c6cd8e8 2339
3e3cec45
MD
2340(define before-error-hook (make-hook))
2341(define after-error-hook (make-hook))
2342(define before-backtrace-hook (make-hook))
2343(define after-backtrace-hook (make-hook))
1c6cd8e8 2344
21ed9efe
MD
2345(define has-shown-debugger-hint? #f)
2346
35c5db87
GH
2347(define (handle-system-error key . args)
2348 (let ((cep (current-error-port)))
8bb7f646 2349 (cond ((not (stack? (fluid-ref the-last-stack))))
21ed9efe 2350 ((memq 'backtrace (debug-options-interface))
04efd24d 2351 (run-hook before-backtrace-hook)
21ed9efe 2352 (newline cep)
755457ec 2353 (display "Backtrace:\n")
8bb7f646 2354 (display-backtrace (fluid-ref the-last-stack) cep)
21ed9efe 2355 (newline cep)
04efd24d
MD
2356 (run-hook after-backtrace-hook)))
2357 (run-hook before-error-hook)
8bb7f646 2358 (apply display-error (fluid-ref the-last-stack) cep args)
04efd24d 2359 (run-hook after-error-hook)
35c5db87
GH
2360 (force-output cep)
2361 (throw 'abort key)))
21ed9efe 2362
0f2d19dd
JB
2363(define (quit . args)
2364 (apply throw 'quit args))
2365
7950df7c
GH
2366(define exit quit)
2367
d590bbf6
MD
2368;;(define has-shown-backtrace-hint? #f) Defined by scm_init_backtrace ()
2369
2370;; Replaced by C code:
2371;;(define (backtrace)
8bb7f646 2372;; (if (fluid-ref the-last-stack)
d590bbf6
MD
2373;; (begin
2374;; (newline)
8bb7f646 2375;; (display-backtrace (fluid-ref the-last-stack) (current-output-port))
d590bbf6
MD
2376;; (newline)
2377;; (if (and (not has-shown-backtrace-hint?)
2378;; (not (memq 'backtrace (debug-options-interface))))
2379;; (begin
2380;; (display
2381;;"Type \"(debug-enable 'backtrace)\" if you would like a backtrace
2382;;automatically if an error occurs in the future.\n")
2383;; (set! has-shown-backtrace-hint? #t))))
2384;; (display "No backtrace available.\n")))
21ed9efe 2385
0f2d19dd
JB
2386(define (error-catching-repl r e p)
2387 (error-catching-loop (lambda () (p (e (r))))))
2388
2389(define (gc-run-time)
2390 (cdr (assq 'gc-time-taken (gc-stats))))
2391
3e3cec45
MD
2392(define before-read-hook (make-hook))
2393(define after-read-hook (make-hook))
870777d7
KN
2394(define before-eval-hook (make-hook 1))
2395(define after-eval-hook (make-hook 1))
2396(define before-print-hook (make-hook 1))
2397(define after-print-hook (make-hook 1))
1c6cd8e8 2398
dc5c2038
MD
2399;;; The default repl-reader function. We may override this if we've
2400;;; the readline library.
2401(define repl-reader
2402 (lambda (prompt)
2403 (display prompt)
2404 (force-output)
04efd24d 2405 (run-hook before-read-hook)
dc5c2038
MD
2406 (read (current-input-port))))
2407
0f2d19dd 2408(define (scm-style-repl)
9d774814 2409
0f2d19dd
JB
2410 (letrec (
2411 (start-gc-rt #f)
2412 (start-rt #f)
0f2d19dd
JB
2413 (repl-report-start-timing (lambda ()
2414 (set! start-gc-rt (gc-run-time))
2415 (set! start-rt (get-internal-run-time))))
2416 (repl-report (lambda ()
2417 (display ";;; ")
2418 (display (inexact->exact
2419 (* 1000 (/ (- (get-internal-run-time) start-rt)
2420 internal-time-units-per-second))))
2421 (display " msec (")
2422 (display (inexact->exact
2423 (* 1000 (/ (- (gc-run-time) start-gc-rt)
2424 internal-time-units-per-second))))
2425 (display " msec in gc)\n")))
480977d0
JB
2426
2427 (consume-trailing-whitespace
2428 (lambda ()
2429 (let ((ch (peek-char)))
2430 (cond
2431 ((eof-object? ch))
2432 ((or (char=? ch #\space) (char=? ch #\tab))
2433 (read-char)
2434 (consume-trailing-whitespace))
2435 ((char=? ch #\newline)
2436 (read-char))))))
0f2d19dd 2437 (-read (lambda ()
dc5c2038
MD
2438 (let ((val
2439 (let ((prompt (cond ((string? scm-repl-prompt)
2440 scm-repl-prompt)
2441 ((thunk? scm-repl-prompt)
2442 (scm-repl-prompt))
2443 (scm-repl-prompt "> ")
2444 (else ""))))
2445 (repl-reader prompt))))
2446
480977d0 2447 ;; As described in R4RS, the READ procedure updates the
e13c54c4 2448 ;; port to point to the first character past the end of
480977d0
JB
2449 ;; the external representation of the object. This
2450 ;; means that it doesn't consume the newline typically
2451 ;; found after an expression. This means that, when
2452 ;; debugging Guile with GDB, GDB gets the newline, which
2453 ;; it often interprets as a "continue" command, making
2454 ;; breakpoints kind of useless. So, consume any
2455 ;; trailing newline here, as well as any whitespace
2456 ;; before it.
e13c54c4
JB
2457 ;; But not if EOF, for control-D.
2458 (if (not (eof-object? val))
2459 (consume-trailing-whitespace))
04efd24d 2460 (run-hook after-read-hook)
0f2d19dd
JB
2461 (if (eof-object? val)
2462 (begin
7950df7c 2463 (repl-report-start-timing)
0f2d19dd
JB
2464 (if scm-repl-verbose
2465 (begin
2466 (newline)
2467 (display ";;; EOF -- quitting")
2468 (newline)))
2469 (quit 0)))
2470 val)))
2471
2472 (-eval (lambda (sourc)
2473 (repl-report-start-timing)
870777d7
KN
2474 (run-hook before-eval-hook sourc)
2475 (let ((val (start-stack 'repl-stack
2476 ;; If you change this procedure
2477 ;; (primitive-eval), please also
2478 ;; modify the repl-stack case in
2479 ;; save-stack so that stack cutting
2480 ;; continues to work.
2481 (primitive-eval sourc))))
2482 (run-hook after-eval-hook sourc)
2483 val)))
2484
0f2d19dd 2485
44484f52
MD
2486 (-print (let ((maybe-print (lambda (result)
2487 (if (or scm-repl-print-unspecified
2488 (not (unspecified? result)))
2489 (begin
2490 (write result)
2491 (newline))))))
2492 (lambda (result)
2493 (if (not scm-repl-silent)
2494 (begin
870777d7 2495 (run-hook before-print-hook result)
3923fa6d 2496 (maybe-print result)
870777d7 2497 (run-hook after-print-hook result)
44484f52
MD
2498 (if scm-repl-verbose
2499 (repl-report))
2500 (force-output))))))
0f2d19dd 2501
8e44e7a0 2502 (-quit (lambda (args)
0f2d19dd
JB
2503 (if scm-repl-verbose
2504 (begin
2505 (display ";;; QUIT executed, repl exitting")
2506 (newline)
2507 (repl-report)))
8e44e7a0 2508 args))
0f2d19dd
JB
2509
2510 (-abort (lambda ()
2511 (if scm-repl-verbose
2512 (begin
2513 (display ";;; ABORT executed.")
2514 (newline)
2515 (repl-report)))
2516 (repl -read -eval -print))))
2517
8e44e7a0
GH
2518 (let ((status (error-catching-repl -read
2519 -eval
2520 -print)))
2521 (-quit status))))
2522
0f2d19dd 2523
0f2d19dd 2524\f
44cf1f0f 2525;;; {IOTA functions: generating lists of numbers}
0f2d19dd 2526
e69cd299
MD
2527(define (iota n)
2528 (let loop ((count (1- n)) (result '()))
2529 (if (< count 0) result
2530 (loop (1- count) (cons count result)))))
0f2d19dd
JB
2531
2532\f
2533;;; {While}
2534;;;
2535;;; with `continue' and `break'.
2536;;;
2537
2538(defmacro while (cond . body)
2539 `(letrec ((continue (lambda () (or (not ,cond) (begin (begin ,@ body) (continue)))))
2540 (break (lambda val (apply throw 'break val))))
2541 (catch 'break
2542 (lambda () (continue))
2543 (lambda v (cadr v)))))
2544
7398c2c2
MD
2545;;; {collect}
2546;;;
2547;;; Similar to `begin' but returns a list of the results of all constituent
2548;;; forms instead of the result of the last form.
2549;;; (The definition relies on the current left-to-right
2550;;; order of evaluation of operands in applications.)
2551
2552(defmacro collect forms
2553 (cons 'list forms))
0f2d19dd 2554
8a6a8671
MV
2555;;; {with-fluids}
2556
2557;; with-fluids is a convenience wrapper for the builtin procedure
2558;; `with-fluids*'. The syntax is just like `let':
2559;;
2560;; (with-fluids ((fluid val)
2561;; ...)
2562;; body)
2563
2564(defmacro with-fluids (bindings . body)
2565 `(with-fluids* (list ,@(map car bindings)) (list ,@(map cadr bindings))
2566 (lambda () ,@body)))
2567
0f2d19dd
JB
2568\f
2569
2570;;; {Macros}
2571;;;
2572
2573;; actually....hobbit might be able to hack these with a little
2574;; coaxing
2575;;
2576
2577(defmacro define-macro (first . rest)
2578 (let ((name (if (symbol? first) first (car first)))
2579 (transformer
2580 (if (symbol? first)
2581 (car rest)
2582 `(lambda ,(cdr first) ,@rest))))
8add1522
KN
2583 `(eval-case
2584 ((load-toplevel)
2585 (define ,name (defmacro:transformer ,transformer)))
2586 (else
2587 (error "define-macro can only be used at the top level")))))
0f2d19dd
JB
2588
2589
2590(defmacro define-syntax-macro (first . rest)
2591 (let ((name (if (symbol? first) first (car first)))
2592 (transformer
2593 (if (symbol? first)
2594 (car rest)
2595 `(lambda ,(cdr first) ,@rest))))
8add1522
KN
2596 `(eval-case
2597 ((load-toplevel)
2598 (define ,name (defmacro:syntax-transformer ,transformer)))
2599 (else
2600 (error "define-syntax-macro can only be used at the top level")))))
645e38d9 2601
0f2d19dd
JB
2602\f
2603;;; {Module System Macros}
2604;;;
2605
2606(defmacro define-module args
7b748b16 2607 `(eval-case
645e38d9
MV
2608 ((load-toplevel)
2609 (process-define-module ',args))
2610 (else
2611 (error "define-module can only be used at the top level"))))
0f2d19dd 2612
89da9036
MV
2613;; the guts of the use-modules macro. add the interfaces of the named
2614;; modules to the use-list of the current module, in order
2615(define (process-use-modules module-names)
2616 (for-each (lambda (module-name)
2617 (let ((mod-iface (resolve-interface module-name)))
2618 (or mod-iface
2619 (error "no such module" module-name))
2620 (module-use! (current-module) mod-iface)))
2621 (reverse module-names)))
2622
33cf699f 2623(defmacro use-modules modules
7b748b16 2624 `(eval-case
645e38d9
MV
2625 ((load-toplevel)
2626 (process-use-modules ',modules))
2627 (else
2628 (error "use-modules can only be used at the top level"))))
33cf699f 2629
cf266109 2630(defmacro use-syntax (spec)
7b748b16 2631 `(eval-case
645e38d9 2632 ((load-toplevel)
7cbaee0c
MD
2633 ,@(if (pair? spec)
2634 `((process-use-modules ',(list spec))
2635 (set-module-transformer! (current-module)
2636 ,(car (last-pair spec))))
2637 `((set-module-transformer! (current-module) ,spec)))
645e38d9
MV
2638 (fluid-set! scm:eval-transformer (module-transformer (current-module))))
2639 (else
2640 (error "use-modules can only be used at the top level"))))
7a0ff2f8 2641
0f2d19dd
JB
2642(define define-private define)
2643
2644(defmacro define-public args
2645 (define (syntax)
2646 (error "bad syntax" (list 'define-public args)))
2647 (define (defined-name n)
2648 (cond
3c5af9ef
JB
2649 ((symbol? n) n)
2650 ((pair? n) (defined-name (car n)))
2651 (else (syntax))))
0f2d19dd 2652 (cond
645e38d9
MV
2653 ((null? args)
2654 (syntax))
2655 (#t
2656 (let ((name (defined-name (car args))))
2657 `(begin
7b748b16 2658 (eval-case ((load-toplevel) (export ,name)))
645e38d9 2659 (define-private ,@args))))))
0f2d19dd
JB
2660
2661(defmacro defmacro-public args
2662 (define (syntax)
2663 (error "bad syntax" (list 'defmacro-public args)))
2664 (define (defined-name n)
2665 (cond
645e38d9
MV
2666 ((symbol? n) n)
2667 (else (syntax))))
0f2d19dd 2668 (cond
645e38d9
MV
2669 ((null? args)
2670 (syntax))
2671 (#t
2672 (let ((name (defined-name (car args))))
2673 `(begin
7b748b16 2674 (eval-case ((load-toplevel) (export ,name)))
645e38d9 2675 (defmacro ,@args))))))
0f2d19dd 2676
90847923
MD
2677(define (module-export! m names)
2678 (let ((public-i (module-public-interface m)))
2679 (for-each (lambda (name)
2680 ;; Make sure there is a local variable:
2681 (module-define! m name (module-ref m name #f))
2682 ;; Make sure that local is exported:
2683 (module-add! public-i name (module-variable m name)))
2684 names)))
2685
a0cc0a01 2686(defmacro export names
7b748b16 2687 `(eval-case
645e38d9
MV
2688 ((load-toplevel)
2689 (module-export! (current-module) ',names))
2690 (else
2691 (error "export can only be used at the top level"))))
a0cc0a01
MD
2692
2693(define export-syntax export)
2694
2695
0f2d19dd
JB
2696(define load load-module)
2697
2698
2699\f
9d774814 2700
9aca88c3
JB
2701;;; {Load emacs interface support if emacs option is given.}
2702
645e38d9
MV
2703(define (named-module-use! user usee)
2704 (module-use! (resolve-module user) (resolve-module usee)))
2705
9aca88c3
JB
2706(define (load-emacs-interface)
2707 (if (memq 'debug-extensions *features*)
2708 (debug-enable 'backtrace))
645e38d9 2709 (named-module-use! '(guile-user) '(ice-9 emacs)))
9aca88c3
JB
2710
2711\f
0f2d19dd 2712
755457ec
MD
2713(define using-readline?
2714 (let ((using-readline? (make-fluid)))
2715 (make-procedure-with-setter
2716 (lambda () (fluid-ref using-readline?))
2717 (lambda (v) (fluid-set! using-readline? v)))))
2718
8e44e7a0 2719(define (top-repl)
9aca88c3
JB
2720
2721 ;; Load emacs interface support if emacs option is given.
2722 (if (and (module-defined? the-root-module 'use-emacs-interface)
6b098fec 2723 (module-ref the-root-module 'use-emacs-interface))
9aca88c3
JB
2724 (load-emacs-interface))
2725
4fdf8b2c 2726 ;; Place the user in the guile-user module.
645e38d9
MV
2727 (process-define-module
2728 '((guile-user)
2729 :use-module (guile) ;so that bindings will be checked here first
2730 :use-module (ice-9 session)
2731 :use-module (ice-9 debug)
2732 :autoload (ice-9 debugger) (debug))) ;load debugger on demand
00b33968 2733 (if (memq 'threads *features*)
645e38d9 2734 (named-module-use! '(guile-user) '(ice-9 threads)))
00b33968 2735 (if (memq 'regex *features*)
645e38d9 2736 (named-module-use! '(guile-user) '(ice-9 regex)))
4fdf8b2c 2737
e1a191a8 2738 (let ((old-handlers #f)
52cfc69b
GH
2739 (signals (if (provided? 'posix)
2740 `((,SIGINT . "User interrupt")
2741 (,SIGFPE . "Arithmetic error")
2742 (,SIGBUS . "Bad memory access (bus error)")
2743 (,SIGSEGV .
2744 "Bad memory access (Segmentation violation)"))
2745 '())))
e1a191a8
GH
2746
2747 (dynamic-wind
2748
2749 ;; call at entry
2750 (lambda ()
2751 (let ((make-handler (lambda (msg)
2752 (lambda (sig)
8087b6be
MD
2753 ;; Make a backup copy of the stack
2754 (fluid-set! before-signal-stack
2755 (fluid-ref the-last-stack))
096d5f90 2756 (save-stack %deliver-signals)
e1a191a8
GH
2757 (scm-error 'signal
2758 #f
2759 msg
2760 #f
2761 (list sig))))))
2762 (set! old-handlers
2763 (map (lambda (sig-msg)
2764 (sigaction (car sig-msg)
2765 (make-handler (cdr sig-msg))))
2766 signals))))
2767
2768 ;; the protected thunk.
2769 (lambda ()
2055a1bc 2770 (let ((status (scm-style-repl)))
04efd24d 2771 (run-hook exit-hook)
2055a1bc 2772 status))
e1a191a8
GH
2773
2774 ;; call at exit.
2775 (lambda ()
2776 (map (lambda (sig-msg old-handler)
2777 (if (not (car old-handler))
2778 ;; restore original C handler.
2779 (sigaction (car sig-msg) #f)
2780 ;; restore Scheme handler, SIG_IGN or SIG_DFL.
2781 (sigaction (car sig-msg)
2782 (car old-handler)
2783 (cdr old-handler))))
bd9e24b3 2784 signals old-handlers)))))
0f2d19dd 2785
02b754d3
GH
2786(defmacro false-if-exception (expr)
2787 `(catch #t (lambda () ,expr)
2788 (lambda args #f)))
2789
2055a1bc
MD
2790;;; This hook is run at the very end of an interactive session.
2791;;;
3e3cec45 2792(define exit-hook (make-hook))
2055a1bc 2793
4d31f0da
JB
2794\f
2795(define-module (guile))
9946dd45 2796
bf4aaed2 2797(append! %load-path (cons "." '()))
6d36532c 2798