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