;;; -*- mode: scheme; coding: utf-8; -*-
-;;;; Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011
-;;;; Free Software Foundation, Inc.
+;;;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+;;;; 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+;;;; 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
(define with-throw-handler #f)
(let ()
- ;; Ideally we'd like to be able to give these default values for all threads,
- ;; even threads not created by Guile; but alack, that does not currently seem
- ;; possible. So wrap the getters in thunks.
- (define %running-exception-handlers (make-fluid))
- (define %exception-handler (make-fluid))
-
- (define (running-exception-handlers)
- (or (fluid-ref %running-exception-handlers)
- (begin
- (fluid-set! %running-exception-handlers '())
- '())))
- (define (exception-handler)
- (or (fluid-ref %exception-handler)
- (begin
- (fluid-set! %exception-handler default-exception-handler)
- default-exception-handler)))
-
(define (default-exception-handler k . args)
(cond
((eq? k 'quit)
(format (current-error-port) "guile: uncaught throw to ~a: ~a\n" k args)
(primitive-exit 1))))
+ (define %running-exception-handlers (make-fluid '()))
+ (define %exception-handler (make-fluid default-exception-handler))
+
(define (default-throw-handler prompt-tag catch-k)
- (let ((prev (exception-handler)))
+ (let ((prev (fluid-ref %exception-handler)))
(lambda (thrown-k . args)
(if (or (eq? thrown-k catch-k) (eqv? catch-k #t))
(apply abort-to-prompt prompt-tag thrown-k args)
(apply prev thrown-k args)))))
(define (custom-throw-handler prompt-tag catch-k pre)
- (let ((prev (exception-handler)))
+ (let ((prev (fluid-ref %exception-handler)))
(lambda (thrown-k . args)
(if (or (eq? thrown-k catch-k) (eqv? catch-k #t))
- (let ((running (running-exception-handlers)))
+ (let ((running (fluid-ref %running-exception-handlers)))
(with-fluids ((%running-exception-handlers (cons pre running)))
(if (not (memq pre running))
(apply pre thrown-k args))
If there is no handler at all, Guile prints an error and then exits."
(if (not (symbol? key))
- ((exception-handler) 'wrong-type-arg "throw"
+ ((fluid-ref %exception-handler) 'wrong-type-arg "throw"
"Wrong type argument in position ~a: ~a" (list 1 key) (list key))
- (apply (exception-handler) key args)))))
+ (apply (fluid-ref %exception-handler) key args)))))
\f
(define pk peek)
+;; Temporary definition; replaced later.
+(define current-warning-port current-error-port)
(define (warn . stuff)
- (with-output-to-port (current-error-port)
+ (with-output-to-port (current-warning-port)
(lambda ()
(newline)
(display ";;; WARNING ")
((do "step" x y)
y)))
-(define-syntax delay
- (syntax-rules ()
- ((_ exp) (make-promise (lambda () exp)))))
+(define-syntax-rule (delay exp)
+ (make-promise (lambda () exp)))
(include-from-path "ice-9/quasisyntax")
(with-syntax ((s (datum->syntax x (syntax-source x))))
#''s)))))
-(define-syntax define-once
- (syntax-rules ()
- ((_ sym val)
- (define sym
- (if (module-locally-bound? (current-module) 'sym) sym val)))))
+(define-syntax-rule (define-once sym val)
+ (define sym
+ (if (module-locally-bound? (current-module) 'sym) sym val)))
;;; The real versions of `map' and `for-each', with cycle detection, and
;;; that use reverse! instead of recursion in the case of `map'.
(let ((filename (or (cadr source) "<unnamed port>"))
(line (caddr source))
(col (cdddr source)))
- (format port "~a:~a:~a: " filename line col))
+ (format port "~a:~a:~a: " filename (1+ line) col))
(format port "ERROR: "))))
(set! set-exception-printer!
(_ (default-printer)))
args))
+ (define (getaddrinfo-error-printer port key args default-printer)
+ (format port "In procedure getaddrinfo: ~a" (gai-strerror (car args))))
+
(set-exception-printer! 'goops-error scm-error-printer)
(set-exception-printer! 'host-not-found scm-error-printer)
(set-exception-printer! 'keyword-argument-error scm-error-printer)
(set-exception-printer! 'wrong-number-of-args scm-error-printer)
(set-exception-printer! 'wrong-type-arg scm-error-printer)
- (set-exception-printer! 'syntax-error syntax-error-printer))
+ (set-exception-printer! 'syntax-error syntax-error-printer)
+
+ (set-exception-printer! 'getaddrinfo-error getaddrinfo-error-printer))
\f
(define (and=> value procedure) (and value (procedure value)))
(define call/cc call-with-current-continuation)
-(define-syntax false-if-exception
- (syntax-rules ()
- ((_ expr)
- (catch #t
- (lambda () expr)
- (lambda (k . args) #f)))))
+(define-syntax-rule (false-if-exception expr)
+ (catch #t
+ (lambda () expr)
+ (lambda (k . args) #f)))
\f
;; properties within the object itself.
(define (make-object-property)
- (define-syntax with-mutex
- (syntax-rules ()
- ((_ lock exp)
- (dynamic-wind (lambda () (lock-mutex lock))
- (lambda () exp)
- (lambda () (unlock-mutex lock))))))
+ (define-syntax-rule (with-mutex lock exp)
+ (dynamic-wind (lambda () (lock-mutex lock))
+ (lambda () exp)
+ (lambda () (unlock-mutex lock))))
(let ((prop (make-weak-key-hash-table))
(lock (make-mutex)))
(make-procedure-with-setter
(thunk)))
(lambda (k . args)
(%start-stack tag (lambda () (apply k args)))))))
-(define-syntax start-stack
- (syntax-rules ()
- ((_ tag exp)
- (%start-stack tag (lambda () exp)))))
+
+(define-syntax-rule (start-stack tag exp)
+ (%start-stack tag (lambda () exp)))
\f
(define (%load-announce file)
(if %load-verbosely
- (with-output-to-port (current-error-port)
+ (with-output-to-port (current-warning-port)
(lambda ()
(display ";;; ")
(display "loading ")
;;; Reader code for various "#c" forms.
;;;
-(define read-eval? (make-fluid))
-(fluid-set! read-eval? #f)
+(define read-eval? (make-fluid #f))
(read-hash-extend #\.
(lambda (c port)
(if (fluid-ref read-eval?)
(error "expected list of integers for version"))
(set-module-version! module version)
(set-module-version! (module-public-interface module) version)))
- (if (pair? duplicates)
- (let ((handlers (lookup-duplicates-handlers duplicates)))
- (set-module-duplicates-handlers! module handlers)))
-
(let ((imports (resolve-imports imports)))
(call-with-deferred-observers
(lambda ()
(error "expected re-exports to be a list of symbols or symbol pairs"))
;; FIXME
(if (not (null? autoloads))
- (apply module-autoload! module autoloads)))))
+ (apply module-autoload! module autoloads))
+ ;; Wait until modules have been loaded to resolve duplicates
+ ;; handlers.
+ (if (pair? duplicates)
+ (let ((handlers (lookup-duplicates-handlers duplicates)))
+ (set-module-duplicates-handlers! module handlers))))))
(if transformer
(if (and (pair? transformer) (list-of symbol? transformer))
flags)
(interface options)
(interface)))
- (define-syntax option-set!
- (syntax-rules ()
- ((_ opt val)
- (eval-when (eval load compile expand)
- (options (append (options) (list 'opt val)))))))))))
+ (define-syntax-rule (option-set! opt val)
+ (eval-when (eval load compile expand)
+ (options (append (options) (list 'opt val)))))))))
(define-option-interface
(debug-options-interface
\f
+;;; {Parameters}
+;;;
+
+(define <parameter>
+ ;; Three fields: the procedure itself, the fluid, and the converter.
+ (make-struct <applicable-struct-vtable> 0 'pwprpr))
+(set-struct-vtable-name! <parameter> '<parameter>)
+
+(define* (make-parameter init #:optional (conv (lambda (x) x)))
+ (let ((fluid (make-fluid (conv init))))
+ (make-struct <parameter> 0
+ (case-lambda
+ (() (fluid-ref fluid))
+ ((x) (let ((prev (fluid-ref fluid)))
+ (fluid-set! fluid (conv x))
+ prev)))
+ fluid conv)))
+
+(define (parameter? x)
+ (and (struct? x) (eq? (struct-vtable x) <parameter>)))
+
+(define (parameter-fluid p)
+ (if (parameter? p)
+ (struct-ref p 1)
+ (scm-error 'wrong-type-arg "parameter-fluid"
+ "Not a parameter: ~S" (list p) #f)))
+
+(define (parameter-converter p)
+ (if (parameter? p)
+ (struct-ref p 2)
+ (scm-error 'wrong-type-arg "parameter-fluid"
+ "Not a parameter: ~S" (list p) #f)))
+
+(define-syntax parameterize
+ (lambda (x)
+ (syntax-case x ()
+ ((_ ((param value) ...) body body* ...)
+ (with-syntax (((p ...) (generate-temporaries #'(param ...))))
+ #'(let ((p param) ...)
+ (if (not (parameter? p))
+ (scm-error 'wrong-type-arg "parameterize"
+ "Not a parameter: ~S" (list p) #f))
+ ...
+ (with-fluids (((struct-ref p 1) ((struct-ref p 2) value))
+ ...)
+ body body* ...)))))))
+
+\f
+;;;
+;;; Current ports as parameters.
+;;;
+
+(let ((fluid->parameter
+ (lambda (fluid conv)
+ (make-struct <parameter> 0
+ (case-lambda
+ (() (fluid-ref fluid))
+ ((x) (let ((prev (fluid-ref fluid)))
+ (fluid-set! fluid (conv x))
+ prev)))
+ fluid conv))))
+ (define-syntax-rule (port-parameterize! binding fluid predicate msg)
+ (begin
+ (set! binding (fluid->parameter (module-ref (current-module) 'fluid)
+ (lambda (x)
+ (if (predicate x) x
+ (error msg x)))))
+ (module-remove! (current-module) 'fluid)))
+
+ (port-parameterize! current-input-port %current-input-port-fluid
+ input-port? "expected an input port")
+ (port-parameterize! current-output-port %current-output-port-fluid
+ output-port? "expected an output port")
+ (port-parameterize! current-error-port %current-error-port-fluid
+ output-port? "expected an output port"))
+
+
+\f
+;;;
+;;; Warnings.
+;;;
+
+(define current-warning-port
+ (make-parameter (current-error-port)
+ (lambda (x)
+ (if (output-port? x)
+ x
+ (error "expected an output port" x)))))
+
+
+\f
+
;;; {Running Repls}
;;;
-(define *repl-stack* (make-fluid))
+(define *repl-stack* (make-fluid '()))
;; Programs can call `batch-mode?' to see if they are running as part of a
;; script or if they are running interactively. REPL implementations ensure that
;; `batch-mode?' returns #f during their extent.
;;
(define (batch-mode?)
- (null? (or (fluid-ref *repl-stack*) '())))
+ (null? (fluid-ref *repl-stack*)))
;; Programs can re-enter batch mode, for example after a fork, by calling
;; `ensure-batch-mode!'. It's not a great interface, though; it would be better
(define repl-reader
(lambda* (prompt #:optional (reader (fluid-ref current-reader)))
(if (not (char-ready?))
- (display (if (string? prompt) prompt (prompt))))
+ (begin
+ (display (if (string? prompt) prompt (prompt)))
+ ;; An interesting situation. The printer resets the column to
+ ;; 0 by printing a newline, but we then advance it by printing
+ ;; the prompt. However the port-column of the output port
+ ;; does not typically correspond with the actual column on the
+ ;; screen, because the input is echoed back! Since the
+ ;; input is line-buffered and thus ends with a newline, the
+ ;; output will really start on column zero. So, here we zero
+ ;; it out. See bug 9664.
+ ;;
+ ;; Note that for similar reasons, the output-line will not
+ ;; reflect the actual line on the screen. But given the
+ ;; possibility of multiline input, the fix is not as
+ ;; straightforward, so we don't bother.
+ ;;
+ ;; Also note that the readline implementation papers over
+ ;; these concerns, because it's readline itself printing the
+ ;; prompt, and not Guile.
+ (set-port-column! (current-output-port) 0)))
(force-output)
(run-hook before-read-hook)
((or reader read) (current-input-port))))
(process-use-modules (list quoted-args ...))
*unspecified*))))))
-(define-syntax use-syntax
- (syntax-rules ()
- ((_ spec ...)
- (begin
- (eval-when (eval load compile expand)
- (issue-deprecation-warning
- "`use-syntax' is deprecated. Please contact guile-devel for more info."))
- (use-modules spec ...)))))
+(define-syntax-rule (use-syntax spec ...)
+ (begin
+ (eval-when (eval load compile expand)
+ (issue-deprecation-warning
+ "`use-syntax' is deprecated. Please contact guile-devel for more info."))
+ (use-modules spec ...)))
(include-from-path "ice-9/r6rs-libraries")
-(define-syntax define-private
- (syntax-rules ()
- ((_ foo bar)
- (define foo bar))))
+(define-syntax-rule (define-private foo bar)
+ (define foo bar))
(define-syntax define-public
(syntax-rules ()
(define name val)
(export name)))))
-(define-syntax defmacro-public
- (syntax-rules ()
- ((_ name args . body)
- (begin
- (defmacro name args . body)
- (export-syntax name)))))
+(define-syntax-rule (defmacro-public name args body ...)
+ (begin
+ (defmacro name args body ...)
+ (export-syntax name)))
;; And now for the most important macro.
-(define-syntax λ
- (syntax-rules ()
- ((_ formals body ...)
- (lambda formals body ...))))
+(define-syntax-rule (λ formals body ...)
+ (lambda formals body ...))
\f
;; Export a local variable
(module-add! public-i external-name var)))))
names)))
-(define-syntax export
- (syntax-rules ()
- ((_ name ...)
- (eval-when (eval load compile expand)
- (call-with-deferred-observers
- (lambda ()
- (module-export! (current-module) '(name ...))))))))
+(define-syntax-rule (export name ...)
+ (eval-when (eval load compile expand)
+ (call-with-deferred-observers
+ (lambda ()
+ (module-export! (current-module) '(name ...))))))
-(define-syntax re-export
- (syntax-rules ()
- ((_ name ...)
- (eval-when (eval load compile expand)
- (call-with-deferred-observers
- (lambda ()
- (module-re-export! (current-module) '(name ...))))))))
+(define-syntax-rule (re-export name ...)
+ (eval-when (eval load compile expand)
+ (call-with-deferred-observers
+ (lambda ()
+ (module-re-export! (current-module) '(name ...))))))
-(define-syntax export!
- (syntax-rules ()
- ((_ name ...)
- (eval-when (eval load compile expand)
- (call-with-deferred-observers
- (lambda ()
- (module-replace! (current-module) '(name ...))))))))
+(define-syntax-rule (export! name ...)
+ (eval-when (eval load compile expand)
+ (call-with-deferred-observers
+ (lambda ()
+ (module-replace! (current-module) '(name ...))))))
-(define-syntax export-syntax
- (syntax-rules ()
- ((_ name ...)
- (export name ...))))
+(define-syntax-rule (export-syntax name ...)
+ (export name ...))
-(define-syntax re-export-syntax
- (syntax-rules ()
- ((_ name ...)
- (re-export name ...))))
+(define-syntax-rule (re-export-syntax name ...)
+ (re-export name ...))
\f
;;;
(define* (make-mutable-parameter init #:optional (converter identity))
- (let ((fluid (make-fluid)))
- (fluid-set! fluid (converter init))
+ (let ((fluid (make-fluid (converter init))))
(case-lambda
(() (fluid-ref fluid))
((val) (fluid-set! fluid (converter val))))))
#f))
(define (warn module name int1 val1 int2 val2 var val)
- (format (current-error-port)
+ (format (current-warning-port)
"WARNING: ~A: `~A' imported from both ~A and ~A\n"
(module-name module)
name
(define (warn-override-core module name int1 val1 int2 val2 var val)
(and (eq? int1 the-scm-module)
(begin
- (format (current-error-port)
+ (format (current-warning-port)
"WARNING: ~A: imported module ~A overrides core binding `~A'\n"
(module-name module)
(module-name int2)
;;; {`load'.}
;;;
;;; Load is tricky when combined with relative paths, compilation, and
-;;; the filesystem. If a path is relative, what is it relative to? The
+;;; the file system. If a path is relative, what is it relative to? The
;;; path of the source file at the time it was compiled? The path of
;;; the compiled file? What if both or either were installed? And how
;;; do you get that information? Tricky, I say.
(define %auto-compilation-options
;; Default `compile-file' option when auto-compiling.
- '(#:warnings (unbound-variable arity-mismatch)))
+ '(#:warnings (unbound-variable arity-mismatch format)))
(define* (load-in-vicinity dir path #:optional reader)
+ (define (canonical->suffix canon)
+ (cond
+ ((string-prefix? "/" canon) canon)
+ ((and (> (string-length canon) 2)
+ (eqv? (string-ref canon 1) #\:))
+ ;; Paths like C:... transform to /C...
+ (string-append "/" (substring canon 0 1) (substring canon 2)))
+ (else canon)))
+
;; Returns the .go file corresponding to `name'. Does not search load
;; paths, only the fallback path. If the .go file is missing or out of
;; date, and auto-compilation is enabled, will try auto-compilation, just
;; partially duplicates functionality from (system base compile).
;;
(define (compiled-file-name canon-path)
+ ;; FIXME: would probably be better just to append SHA1(canon-path)
+ ;; to the %compile-fallback-path, to avoid deep directory stats.
(and %compile-fallback-path
(string-append
%compile-fallback-path
- ;; no need for '/' separator here, canon-path is absolute
- canon-path
+ (canonical->suffix canon-path)
(cond ((or (null? %load-compiled-extensions)
(string-null? (car %load-compiled-extensions)))
(warn "invalid %load-compiled-extensions"
go-path
(begin
(if gostat
- (format (current-error-port)
+ (format (current-warning-port)
";;; note: source file ~a\n;;; newer than compiled ~a\n"
name go-path))
(cond
(%load-should-auto-compile
(%warn-auto-compilation-enabled)
- (format (current-error-port) ";;; compiling ~a\n" name)
+ (format (current-warning-port) ";;; compiling ~a\n" name)
(let ((cfn
((module-ref
(resolve-interface '(system base compile))
name
#:opts %auto-compilation-options
#:env (current-module))))
- (format (current-error-port) ";;; compiled ~a\n" cfn)
+ (format (current-warning-port) ";;; compiled ~a\n" cfn)
cfn))
(else #f))))))
(lambda (k . args)
- (format (current-error-port)
- ";;; WARNING: compilation of ~a failed:\n;;; key ~a, throw_args ~s\n"
- name k args)
+ (format (current-warning-port)
+ ";;; WARNING: compilation of ~a failed:\n" name)
+ (for-each (lambda (s)
+ (if (not (string-null? s))
+ (format (current-warning-port) ";;; ~a\n" s)))
+ (string-split
+ (call-with-output-string
+ (lambda (port) (print-exception port #f k args)))
+ #\newline))
#f)))
(define (absolute-path? path)
(and go-path
(fresh-compiled-file-name abs-path go-path)))))))
(if cfn
- (load-compiled cfn)
+ (begin
+ (if %load-hook
+ (%load-hook abs-path))
+ (load-compiled cfn))
(start-stack 'load-stack
(primitive-load abs-path)))))
srfi-4 ;; homogenous numeric vectors
srfi-6 ;; open-input-string etc, in the guile core
srfi-13 ;; string library
- srfi-23 ;; `error` procedure
srfi-14 ;; character sets
+ srfi-23 ;; `error` procedure
+ srfi-39 ;; parameterize
srfi-55 ;; require-extension
srfi-61 ;; general cond clause
))
((args ...) (generate-temporaries #'(formals ...))))
#`(begin
(define (proc-name formals ...)
- body ...)
+ (fluid-let-syntax ((name (identifier-syntax proc-name)))
+ body ...))
(define-syntax name
(lambda (x)
(syntax-case x ()
((_ args ...)
- #'((lambda (formals ...)
- body ...)
+ #'((fluid-let-syntax ((name (identifier-syntax proc-name)))
+ (lambda (formals ...)
+ body ...))
args ...))
(_
(identifier? x)