;;; installed-scm-file
-;;;; Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002, 2003 Free Software Foundation, Inc.
+;;;; Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006
+;;;; Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
-;;;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;;;;
+
\f
;;; Commentary:
;;; Code:
\f
-;;; {Deprecation}
-;;;
-
-;; We don't have macros here, but we do want to define
-;; `begin-deprecated' early.
-
-(define begin-deprecated
- (procedure->memoizing-macro
- (lambda (exp env)
- (if (include-deprecated-features)
- `(begin ,@(cdr exp))
- `#f))))
-\f
;;; {Features}
-;;
+;;;
(define (provide sym)
(if (not (memq sym *features*))
(set! *features* (cons sym *features*))))
-;;; Return #t iff FEATURE is available to this Guile interpreter.
-;;; In SLIB, provided? also checks to see if the module is available.
-;;; We should do that too, but don't.
+;; Return #t iff FEATURE is available to this Guile interpreter. In SLIB,
+;; provided? also checks to see if the module is available. We should do that
+;; too, but don't.
+
(define (provided? feature)
(and (memq feature *features*) #t))
-(begin-deprecated
- (define (feature? sym)
- (issue-deprecation-warning
- "`feature?' is deprecated. Use `provided?' instead.")
- (provided? sym)))
+;; let format alias simple-format until the more complete version is loaded
-;;; let format alias simple-format until the more complete version is loaded
(define format simple-format)
+;; this is scheme wrapping the C code so the final pred call is a tail call,
+;; per SRFI-13 spec
+(define (string-any char_pred s . rest)
+ (let ((start (if (null? rest)
+ 0 (car rest)))
+ (end (if (or (null? rest) (null? (cdr rest)))
+ (string-length s) (cadr rest))))
+ (if (and (procedure? char_pred)
+ (> end start)
+ (<= end (string-length s))) ;; let c-code handle range error
+ (or (string-any-c-code char_pred s start (1- end))
+ (char_pred (string-ref s (1- end))))
+ (string-any-c-code char_pred s start end))))
+
+;; this is scheme wrapping the C code so the final pred call is a tail call,
+;; per SRFI-13 spec
+(define (string-every char_pred s . rest)
+ (let ((start (if (null? rest)
+ 0 (car rest)))
+ (end (if (or (null? rest) (null? (cdr rest)))
+ (string-length s) (cadr rest))))
+ (if (and (procedure? char_pred)
+ (> end start)
+ (<= end (string-length s))) ;; let c-code handle range error
+ (and (string-every-c-code char_pred s start (1- end))
+ (char_pred (string-ref s (1- end))))
+ (string-every-c-code char_pred s start end))))
+
+;; A variant of string-fill! that we keep for compatability
+;;
+(define (substring-fill! str start end fill)
+ (string-fill! str fill start end))
+
\f
-;;; {R4RS compliance}
-(primitive-load-path "ice-9/r4rs.scm")
+;;; {EVAL-CASE}
+;;;
+
+;; (eval-case ((situation*) forms)* (else forms)?)
+;;
+;; Evaluate certain code based on the situation that eval-case is used
+;; in. The only defined situation right now is `load-toplevel' which
+;; triggers for code evaluated at the top-level, for example from the
+;; REPL or when loading a file.
+
+(define eval-case
+ (procedure->memoizing-macro
+ (lambda (exp env)
+ (define (toplevel-env? env)
+ (or (not (pair? env)) (not (pair? (car env)))))
+ (define (syntax)
+ (error "syntax error in eval-case"))
+ (let loop ((clauses (cdr exp)))
+ (cond
+ ((null? clauses)
+ #f)
+ ((not (list? (car clauses)))
+ (syntax))
+ ((eq? 'else (caar clauses))
+ (or (null? (cdr clauses))
+ (syntax))
+ (cons 'begin (cdar clauses)))
+ ((not (list? (caar clauses)))
+ (syntax))
+ ((and (toplevel-env? env)
+ (memq 'load-toplevel (caar clauses)))
+ (cons 'begin (cdar clauses)))
+ (else
+ (loop (cdr clauses))))))))
\f
-;;; {Deprecated stuff}
-(begin-deprecated
- (primitive-load-path "ice-9/deprecated.scm"))
+;;; {Defmacros}
+;;;
+;;; Depends on: features, eval-case
+;;;
+
+(define macro-table (make-weak-key-hash-table 61))
+(define xformer-table (make-weak-key-hash-table 61))
+
+(define (defmacro? m) (hashq-ref macro-table m))
+(define (assert-defmacro?! m) (hashq-set! macro-table m #t))
+(define (defmacro-transformer m) (hashq-ref xformer-table m))
+(define (set-defmacro-transformer! m t) (hashq-set! xformer-table m t))
+
+(define defmacro:transformer
+ (lambda (f)
+ (let* ((xform (lambda (exp env)
+ (copy-tree (apply f (cdr exp)))))
+ (a (procedure->memoizing-macro xform)))
+ (assert-defmacro?! a)
+ (set-defmacro-transformer! a f)
+ a)))
+
+
+(define defmacro
+ (let ((defmacro-transformer
+ (lambda (name parms . body)
+ (let ((transformer `(lambda ,parms ,@body)))
+ `(eval-case
+ ((load-toplevel)
+ (define ,name (defmacro:transformer ,transformer)))
+ (else
+ (error "defmacro can only be used at the top level")))))))
+ (defmacro:transformer defmacro-transformer)))
+
+(define defmacro:syntax-transformer
+ (lambda (f)
+ (procedure->syntax
+ (lambda (exp env)
+ (copy-tree (apply f (cdr exp)))))))
+
+
+;; XXX - should the definition of the car really be looked up in the
+;; current module?
+
+(define (macroexpand-1 e)
+ (cond
+ ((pair? e) (let* ((a (car e))
+ (val (and (symbol? a) (local-ref (list a)))))
+ (if (defmacro? val)
+ (apply (defmacro-transformer val) (cdr e))
+ e)))
+ (#t e)))
+
+(define (macroexpand e)
+ (cond
+ ((pair? e) (let* ((a (car e))
+ (val (and (symbol? a) (local-ref (list a)))))
+ (if (defmacro? val)
+ (macroexpand (apply (defmacro-transformer val) (cdr e)))
+ e)))
+ (#t e)))
+
+(provide 'defmacro)
\f
-;;; {Simple Debugging Tools}
-;;
+;;; {Deprecation}
+;;;
+;;; Depends on: defmacro
+;;;
+
+(defmacro begin-deprecated forms
+ (if (include-deprecated-features)
+ (cons begin forms)
+ #f))
+\f
+
+;;; {R4RS compliance}
+;;;
+
+(primitive-load-path "ice-9/r4rs.scm")
+
+\f
+
+;;; {Simple Debugging Tools}
+;;;
;; peek takes any number of arguments, writes them to the
;; current ouput port, and returns the last argument.
(car (last-pair stuff)))))
\f
+
;;; {Trivial Functions}
;;;
(define (identity x) x)
-(define (1+ n) (+ n 1))
-(define (1- n) (+ n -1))
(define (and=> value procedure) (and value (procedure value)))
(define call/cc call-with-current-continuation)
(define (apply-to-args args fn) (apply fn args))
+(defmacro false-if-exception (expr)
+ `(catch #t (lambda () ,expr)
+ (lambda args #f)))
+
+\f
+
+;;; {General Properties}
+;;;
+
+;; This is a more modern interface to properties. It will replace all
+;; other property-like things eventually.
+
+(define (make-object-property)
+ (let ((prop (primitive-make-property #f)))
+ (make-procedure-with-setter
+ (lambda (obj) (primitive-property-ref prop obj))
+ (lambda (obj val) (primitive-property-set! prop obj val)))))
+
\f
;;; {Symbol Properties}
(if pair
(symbol-pset! sym (delq! pair (symbol-pref sym))))))
-;;; {General Properties}
-;;;
-
-;; This is a more modern interface to properties. It will replace all
-;; other property-like things eventually.
-
-(define (make-object-property)
- (let ((prop (primitive-make-property #f)))
- (make-procedure-with-setter
- (lambda (obj) (primitive-property-ref prop obj))
- (lambda (obj val) (primitive-property-set! prop obj val)))))
-
\f
;;; {Arrays}
;;;
-(if (provided? 'array)
- (primitive-load-path "ice-9/arrays.scm"))
+(define (array-shape a)
+ (map (lambda (ind) (if (number? ind) (list 0 (+ -1 ind)) ind))
+ (array-dimensions a)))
\f
+
;;; {Keywords}
;;;
-(define (symbol->keyword symbol)
- (make-keyword-from-dash-symbol (symbol-append '- symbol)))
-
-(define (keyword->symbol kw)
- (let ((sym (symbol->string (keyword-dash-symbol kw))))
- (string->symbol (substring sym 1 (string-length sym)))))
-
(define (kw-arg-ref args kw)
(let ((rem (member kw args)))
(and rem (pair? (cdr rem)) (cadr rem))))
\f
;;; {Structs}
+;;;
(define (struct-layout s)
(struct-ref (struct-vtable s) vtable-index-layout))
\f
-;;; Environments
+;;; {Environments}
+;;;
(define the-environment
(procedure->syntax
(define (environment-module env)
(let ((closure (and (pair? env) (car (last-pair env)))))
- (and closure (procedure-property closure 'module))))
+ (and closure (eval-closure-module closure))))
\f
+
;;; {Records}
;;;
(provide 'record)
\f
+
;;; {Booleans}
;;;
(define (->bool x) (not (not x)))
\f
+
;;; {Symbols}
;;;
(string->symbol (apply string args)))
\f
+
;;; {Lists}
;;;
n
(loop (+ n 1) (cdr l))))))
-(define (make-list n . init)
- (if (pair? init) (set! init (car init)))
- (let loop ((answer '())
- (n n))
- (if (<= n 0)
- answer
- (loop (cons init answer) (- n 1)))))
-
\f
+
;;; {and-map and or-map}
;;;
;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
#f))
\f
+
;;; {Error Handling}
;;;
(putenv name))
\f
+
;;; {Load Paths}
;;;
file)))
\f
+
;;; {Help for scm_shell}
+;;;
;;; The argument-processing code used by Guile-based shells generates
;;; Scheme code based on the argument list. This page contains help
;;; functions for the code it generates.
+;;;
(define (command-line) (program-arguments))
(primitive-load init-file))))
\f
+
;;; {Loading by paths}
+;;;
;;; Load a Scheme source file named NAME, searching for it in the
;;; directories listed in %load-path, and applying each of the file
\f
+
;;; {Transcendental Functions}
;;;
;;; Derived from "Transcen.scm", Complex trancendental functions for SCM.
(define expt
(let ((integer-expt integer-expt))
(lambda (z1 z2)
- (cond ((integer? z2)
- (if (negative? z2)
- (/ 1 (integer-expt z1 (- z2)))
- (integer-expt z1 z2)))
+ (cond ((and (exact? z2) (integer? z2))
+ (integer-expt z1 z2))
((and (real? z2) (real? z1) (>= z1 0))
($expt z1 z2))
(else
;;; {Reader Extensions}
;;;
-
;;; Reader code for various "#c" forms.
;;;
"#. read expansion found and read-eval? is #f."))))
\f
+
;;; {Command Line Options}
;;;
;;;
\f
+
;;; {Printing Modules}
+;;;
+
;; This is how modules are printed. You can re-define it.
;; (Redefining is actually more complicated than simply redefining
;; %print-module because that would only change the binding and not
;; is a (CLOSURE module symbol) which, as a last resort, can provide
;; bindings that would otherwise not be found locally in the module.
;;
-;; NOTE: If you change here, you also need to change libguile/modules.h.
+;; NOTE: If you change anything here, you also need to change
+;; libguile/modules.h.
;;
(define module-type
(make-record-type 'module
(set-procedure-property! closure 'module module))))
\f
+
;;; {Observer protocol}
;;;
(hash-fold (lambda (id proc res) (proc m)) #f (module-weak-observers m)))
\f
+
;;; {Module Searching in General}
;;;
;;; We sometimes want to look for properties of a symbol
\f
+
;;; {Adding Variables to Modules}
;;;
-;;;
-
;; module-make-local-var! module symbol
;;
;; the standard eval closure defines a binding
(module-modified m)
b)))
- (and (module-binder m)
- ((module-binder m) m v #t))
- (begin
- (let ((answer (make-undefined-variable)))
- (module-add! m v answer)
- answer))))
+
+ ;; No local variable yet, so we need to create a new one. That
+ ;; new variable is initialized with the old imported value of V,
+ ;; if there is one.
+ (let ((imported-var (module-variable m v))
+ (local-var (or (and (module-binder m)
+ ((module-binder m) m v #t))
+ (begin
+ (let ((answer (make-undefined-variable)))
+ (module-add! m v answer)
+ answer)))))
+ (if (and imported-var (not (variable-bound? local-var)))
+ (variable-set! local-var (variable-ref imported-var)))
+ local-var)))
;; module-ensure-local-variable! module symbol
;;
(hash-for-each proc (module-obarray module)))
(define (module-map proc module)
- (hash-map proc (module-obarray module)))
+ (hash-map->list proc (module-obarray module)))
\f
\f
+
;;; {Module-based Loading}
;;;
(define basic-load load)
-(define (load-module filename)
+(define (load-module filename . reader)
(save-module-excursion
(lambda ()
(let ((oldname (and (current-load-port)
(port-filename (current-load-port)))))
- (basic-load (if (and oldname
- (> (string-length filename) 0)
- (not (char=? (string-ref filename 0) #\/))
- (not (string=? (dirname oldname) ".")))
- (string-append (dirname oldname) "/" filename)
- filename))))))
+ (apply basic-load
+ (if (and oldname
+ (> (string-length filename) 0)
+ (not (char=? (string-ref filename 0) #\/))
+ (not (string=? (dirname oldname) ".")))
+ (string-append (dirname oldname) "/" filename)
+ filename)
+ reader)))))
\f
+
;;; {MODULE-REF -- exported}
-;;
+;;;
+
;; Returns the value of a variable called NAME in MODULE or any of its
;; used modules. If there is no such variable, then if the optional third
;; argument DEFAULT is present, it is returned; otherwise an error is signaled.
(module-modified module)))
\f
+
;;; {Recursive Namespaces}
;;;
-;;;
;;; A hierarchical namespace emerges if we consider some module to be
;;; root, and variables bound to modules as nested namespaces.
;;;
\f
-;;; {The (app) module}
+
+;;; {The (%app) module}
;;;
;;; The root of conventionally named objects not directly in the top level.
;;;
-;;; (app modules)
-;;; (app modules guile)
+;;; (%app modules)
+;;; (%app modules guile)
;;;
;;; The directory of all modules and the standard root module.
;;;
;; NOTE: This binding is used in libguile/modules.c.
;;
(define (resolve-module name . maybe-autoload)
- (let ((full-name (append '(app modules) name)))
- (let ((already (local-ref full-name)))
+ (let ((full-name (append '(%app modules) name)))
+ (let ((already (nested-ref the-root-module full-name)))
(if already
;; The module already exists...
(if (and (or (null? maybe-autoload) (car maybe-autoload))
;;
(set-current-module the-root-module)
-(define app (make-module 31))
-(local-define '(app modules) (make-module 31))
-(local-define '(app modules guile) the-root-module)
+(define %app (make-module 31))
+(define app %app) ;; for backwards compatability
+(local-define '(%app modules) (make-module 31))
+(local-define '(%app modules guile) the-root-module)
-;; (define-special-value '(app modules new-ws) (lambda () (make-scm-module)))
+;; (define-special-value '(%app modules new-ws) (lambda () (make-scm-module)))
(define (try-load-module name)
(or (begin-deprecated (try-module-linked name))
(exports '())
(re-exports '())
(replacements '()))
+
(if (null? kws)
(call-with-deferred-observers
(lambda ()
;; module.
(define module-defined-hook (make-hook 1))
+\f
+
;;; {Autoload}
+;;;
(define (make-autoload-interface module name bindings)
(let ((b (lambda (a sym definep)
(let ((i (module-public-interface (resolve-module name))))
(if (not i)
(error "missing interface for module" name))
- ;; Replace autoload-interface with interface
- (set-car! (memq a (module-uses module)) i)
+ (let ((autoload (memq a (module-uses module))))
+ ;; Replace autoload-interface with actual interface if
+ ;; that has not happened yet.
+ (if (pair? autoload)
+ (set-car! autoload i)))
(module-local-variable i sym))))))
(module-constructor (make-hash-table 0) '() b #f #f name 'autoload #f #f
'() (make-weak-value-hash-table 31) 0)))
(define load-compiled #f)
\f
+
;;; {Autoloading modules}
+;;;
(define autoloads-in-progress '())
(load-file load-compiled full)))
((%search-load-path file)
=> (lambda (full)
- (load-file primitive-load full))))))
+ (with-fluids ((current-reader #f))
+ (load-file primitive-load full)))))))
(lambda () (set-autoloaded! dir-hint name didit)))
didit))))
\f
-;;; Dynamic linking of modules
+
+;;; {Dynamic linking of modules}
+;;;
(define autoloads-done '((guile . guile)))
(set! autoloads-done (delete! n autoloads-done))
(set! autoloads-in-progress (delete! n autoloads-in-progress)))))
-
-
-\f
-;; {EVAL-CASE}
-;;
-;; (eval-case ((situation*) forms)* (else forms)?)
-;;
-;; Evaluate certain code based on the situation that eval-case is used
-;; in. The only defined situation right now is `load-toplevel' which
-;; triggers for code evaluated at the top-level, for example from the
-;; REPL or when loading a file.
-
-(define eval-case
- (procedure->memoizing-macro
- (lambda (exp env)
- (define (toplevel-env? env)
- (or (not (pair? env)) (not (pair? (car env)))))
- (define (syntax)
- (error "syntax error in eval-case"))
- (let loop ((clauses (cdr exp)))
- (cond
- ((null? clauses)
- #f)
- ((not (list? (car clauses)))
- (syntax))
- ((eq? 'else (caar clauses))
- (or (null? (cdr clauses))
- (syntax))
- (cons 'begin (cdar clauses)))
- ((not (list? (caar clauses)))
- (syntax))
- ((and (toplevel-env? env)
- (memq 'load-toplevel (caar clauses)))
- (cons 'begin (cdar clauses)))
- (else
- (loop (cdr clauses))))))))
-
-\f
-;;; {Macros}
-;;;
-
-(define (primitive-macro? m)
- (and (macro? m)
- (not (macro-transformer m))))
-
-;;; {Defmacros}
-;;;
-(define macro-table (make-weak-key-hash-table 61))
-(define xformer-table (make-weak-key-hash-table 61))
-
-(define (defmacro? m) (hashq-ref macro-table m))
-(define (assert-defmacro?! m) (hashq-set! macro-table m #t))
-(define (defmacro-transformer m) (hashq-ref xformer-table m))
-(define (set-defmacro-transformer! m t) (hashq-set! xformer-table m t))
-
-(define defmacro:transformer
- (lambda (f)
- (let* ((xform (lambda (exp env)
- (copy-tree (apply f (cdr exp)))))
- (a (procedure->memoizing-macro xform)))
- (assert-defmacro?! a)
- (set-defmacro-transformer! a f)
- a)))
-
-
-(define defmacro
- (let ((defmacro-transformer
- (lambda (name parms . body)
- (let ((transformer `(lambda ,parms ,@body)))
- `(eval-case
- ((load-toplevel)
- (define ,name (defmacro:transformer ,transformer)))
- (else
- (error "defmacro can only be used at the top level")))))))
- (defmacro:transformer defmacro-transformer)))
-
-(define defmacro:syntax-transformer
- (lambda (f)
- (procedure->syntax
- (lambda (exp env)
- (copy-tree (apply f (cdr exp)))))))
-
-
-;; XXX - should the definition of the car really be looked up in the
-;; current module?
-
-(define (macroexpand-1 e)
- (cond
- ((pair? e) (let* ((a (car e))
- (val (and (symbol? a) (local-ref (list a)))))
- (if (defmacro? val)
- (apply (defmacro-transformer val) (cdr e))
- e)))
- (#t e)))
-
-(define (macroexpand e)
- (cond
- ((pair? e) (let* ((a (car e))
- (val (and (symbol? a) (local-ref (list a)))))
- (if (defmacro? val)
- (macroexpand (apply (defmacro-transformer val) (cdr e)))
- e)))
- (#t e)))
-
-(provide 'defmacro)
-
\f
;;; {Run-time options}
+;;;
(define define-option-interface
(let* ((option-name car)
(catch #t
(lambda ()
- (lazy-catch #t
- (lambda ()
- (call-with-unblocked-asyncs
- (lambda ()
- (with-traps
- (lambda ()
- (first)
-
- ;; This line is needed because mark
- ;; doesn't do closures quite right.
- ;; Unreferenced locals should be
- ;; collected.
- ;;
- (set! first #f)
- (let loop ((v (thunk)))
- (loop (thunk)))
- #f)))))
-
- ;; Use a closure here rather than
- ;; just `lazy-handler-dispatch' so
- ;; that lookup of
- ;; lazy-handler-dispatch's value is
- ;; deferred until a throw occurs.
- ;; This means that if code executed
- ;; in the REPL just above set!s
- ;; lazy-handler-dispatch, the new
- ;; value will be used to handle the
- ;; next throw from the REPL.
- (lambda args
- (apply lazy-handler-dispatch args))))
+ (call-with-unblocked-asyncs
+ (lambda ()
+ (with-traps
+ (lambda ()
+ (first)
+
+ ;; This line is needed because mark
+ ;; doesn't do closures quite right.
+ ;; Unreferenced locals should be
+ ;; collected.
+ (set! first #f)
+ (let loop ((v (thunk)))
+ (loop (thunk)))
+ #f)))))
(lambda (key . args)
(case key
(cond ((= (length args) 4)
(apply handle-system-error key args))
(else
- (apply bad-throw key args))))))))))
+ (apply bad-throw key args)))))))
+
+ ;; Note that having just `lazy-handler-dispatch'
+ ;; here is connected with the mechanism that
+ ;; produces a nice backtrace upon error. If, for
+ ;; example, this is replaced with (lambda args
+ ;; (apply lazy-handler-dispatch args)), the stack
+ ;; cutting (in save-stack) goes wrong and ends up
+ ;; saving no stack at all, so there is no
+ ;; backtrace.
+ lazy-handler-dispatch)))
+
(if next (loop next) status)))
(set! set-batch-mode?! (lambda (arg)
(cond (arg
(let ((cep (current-error-port)))
(cond ((not (stack? (fluid-ref the-last-stack))))
((memq 'backtrace (debug-options-interface))
- (run-hook before-backtrace-hook)
- (newline cep)
- (display "Backtrace:\n")
- (display-backtrace (fluid-ref the-last-stack) cep)
- (newline cep)
- (run-hook after-backtrace-hook)))
+ (let ((highlights (if (or (eq? key 'wrong-type-arg)
+ (eq? key 'out-of-range))
+ (list-ref args 3)
+ '())))
+ (run-hook before-backtrace-hook)
+ (newline cep)
+ (display "Backtrace:\n")
+ (display-backtrace (fluid-ref the-last-stack) cep
+ #f #f highlights)
+ (newline cep)
+ (run-hook after-backtrace-hook))))
(run-hook before-error-hook)
(apply display-error (fluid-ref the-last-stack) cep args)
(run-hook after-error-hook)
(display prompt)
(force-output)
(run-hook before-read-hook)
- (read (current-input-port))))
+ ((or (fluid-ref current-reader) read) (current-input-port))))
(define (scm-style-repl)
\f
+
;;; {IOTA functions: generating lists of numbers}
+;;;
(define (iota n)
(let loop ((count (1- n)) (result '()))
(loop (1- count) (cons count result)))))
\f
+
;;; {collect}
;;;
;;; Similar to `begin' but returns a list of the results of all constituent
;;; forms instead of the result of the last form.
;;; (The definition relies on the current left-to-right
;;; order of evaluation of operands in applications.)
+;;;
(defmacro collect forms
(cons 'list forms))
+\f
+
;;; {with-fluids}
+;;;
;; with-fluids is a convenience wrapper for the builtin procedure
;; `with-fluids*'. The syntax is just like `let':
;; body)
(defmacro with-fluids (bindings . body)
- `(with-fluids* (list ,@(map car bindings)) (list ,@(map cadr bindings))
- (lambda () ,@body)))
+ (let ((fluids (map car bindings))
+ (values (map cadr bindings)))
+ (if (and (= (length fluids) 1) (= (length values) 1))
+ `(with-fluid* ,(car fluids) ,(car values) (lambda () ,@body))
+ `(with-fluids* (list ,@fluids) (list ,@values)
+ (lambda () ,@body)))))
\f
;; coaxing
;;
+(define (primitive-macro? m)
+ (and (macro? m)
+ (not (macro-transformer m))))
+
(defmacro define-macro (first . rest)
(let ((name (if (symbol? first) first (car first)))
(transformer
(else
(error "define-syntax-macro can only be used at the top level")))))
+\f
+
;;; {While}
;;;
;;; with `continue' and `break'.
;; `while' even when recursing. `while-helper' is an easy way to keep the
;; `key' binding away from the cond and body code.
;;
+;; FIXME: This is supposed to have an `unquote' on the `do' the same used
+;; for lambda and not, so as to protect against any user rebinding of that
+;; symbol, but unfortunately an unquote breaks with ice-9 syncase, eg.
+;;
+;; (use-modules (ice-9 syncase))
+;; (while #f)
+;; => ERROR: invalid syntax ()
+;;
+;; This is probably a bug in syncase.
+;;
(define-macro (while cond . body)
(define (while-helper proc)
(do ((key (make-symbol "while-key")))
(lambda () (throw key #f))))
(lambda (key arg) arg)))))
`(,while-helper (,lambda (break continue)
- (,do ()
+ (do ()
((,not ,cond))
,@body)
#t)))
\f
+
;;; {Module System Macros}
;;;
var))
\f
+
;;; {Parameters}
;;;
(make fluid converter)))))
\f
+
;;; {Handling of duplicate imported bindings}
;;;
;;;
;;; Currently, the following feature identifiers are supported:
;;;
-;;; guile r5rs srfi-0
+;;; guile r5rs srfi-0 srfi-4 srfi-6 srfi-13 srfi-14 srfi-55 srfi-61
;;;
;;; Remember to update the features list when adding more SRFIs.
+;;;
(define %cond-expand-features
;; Adjust the above comment when changing this.
- '(guile r5rs srfi-0))
+ '(guile
+ r5rs
+ srfi-0 ;; cond-expand itself
+ srfi-4 ;; homogenous numeric vectors
+ srfi-6 ;; open-input-string etc, in the guile core
+ srfi-13 ;; string library
+ srfi-14 ;; character sets
+ srfi-55 ;; require-extension
+ srfi-61 ;; general cond clause
+ ))
;; This table maps module public interfaces to the list of features.
;;
\f
+;;; srfi-55: require-extension
+;;;
+
+(define-macro (require-extension extension-spec)
+ ;; This macro only handles the srfi extension, which, at present, is
+ ;; the only one defined by the standard.
+ (if (not (pair? extension-spec))
+ (scm-error 'wrong-type-arg "require-extension"
+ "Not an extension: ~S" (list extension-spec) #f))
+ (let ((extension (car extension-spec))
+ (extension-args (cdr extension-spec)))
+ (case extension
+ ((srfi)
+ (let ((use-list '()))
+ (for-each
+ (lambda (i)
+ (if (not (integer? i))
+ (scm-error 'wrong-type-arg "require-extension"
+ "Invalid srfi name: ~S" (list i) #f))
+ (let ((srfi-sym (string->symbol
+ (string-append "srfi-" (number->string i)))))
+ (if (not (memq srfi-sym %cond-expand-features))
+ (set! use-list (cons `(use-modules (srfi ,srfi-sym))
+ use-list)))))
+ extension-args)
+ (if (pair? use-list)
+ ;; i.e. (begin (use-modules x) (use-modules y) (use-modules z))
+ `(begin ,@(reverse! use-list)))))
+ (else
+ (scm-error
+ 'wrong-type-arg "require-extension"
+ "Not a recognized extension type: ~S" (list extension) #f)))))
+
+\f
+
;;; {Load emacs interface support if emacs option is given.}
+;;;
(define (named-module-use! user usee)
(module-use! (resolve-module user) (resolve-interface usee)))
(module-use! guile-user-module (resolve-interface '(ice-9 session)))
(module-use! guile-user-module (resolve-interface '(ice-9 debug)))
;; so that builtin bindings will be checked first
+ (module-use! guile-user-module (resolve-interface '(ice-9 r5rs)))
(module-use! guile-user-module (resolve-interface '(guile)))
(set-current-module guile-user-module)
(cdr old-handler))))
signals old-handlers))))))
-(defmacro false-if-exception (expr)
- `(catch #t (lambda () ,expr)
- (lambda args #f)))
-
;;; This hook is run at the very end of an interactive session.
;;;
(define exit-hook (make-hook))
\f
-(append! %load-path (list "."))
-;; Place the user in the guile-user module.
-;;
+;;; {Deprecated stuff}
+;;;
+
+(begin-deprecated
+ (define (feature? sym)
+ (issue-deprecation-warning
+ "`feature?' is deprecated. Use `provided?' instead.")
+ (provided? sym)))
+
+(begin-deprecated
+ (primitive-load-path "ice-9/deprecated.scm"))
+
+\f
+
+;;; Place the user in the guile-user module.
+;;;
(define-module (guile-user))