expt implemented in C, handles complex numbers
[bpt/guile.git] / module / ice-9 / boot-9.scm
index bb66ccf..b3d9d4f 100644 (file)
@@ -1,12 +1,12 @@
-;;; installed-scm-file
+;;; -*- mode: scheme; coding: utf-8; -*-
 
-;;;; Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2009
+;;;; Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009
 ;;;; 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
 ;;;; License as published by the Free Software Foundation; either
-;;;; version 2.1 of the License, or (at your option) any later version.
+;;;; version 3 of the License, or (at your option) any later version.
 ;;;; 
 ;;;; This library is distributed in the hope that it will be useful,
 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -68,6 +68,7 @@
 
 (define pk peek)
 
+
 (define (warn . stuff)
   (with-output-to-port (current-error-port)
     (lambda ()
   (syntax-rules ()
     ((_ exp) (make-promise (lambda () exp)))))
 
+(include-from-path "ice-9/quasisyntax")
+
+;;; @bind is used by the old elisp code as a dynamic scoping mechanism.
+;;; Please let the Guile developers know if you are using this macro.
+;;;
+(define-syntax @bind
+  (lambda (x)
+    (define (bound-member id ids)
+      (cond ((null? ids) #f)
+            ((bound-identifier=? id (car ids)) #t)
+            ((bound-member (car ids) (cdr ids)))))
+    
+    (syntax-case x ()
+      ((_ () b0 b1 ...)
+       #'(let () b0 b1 ...))
+      ((_ ((id val) ...) b0 b1 ...)
+       (and-map identifier? #'(id ...))
+       (if (let lp ((ids #'(id ...)))
+             (cond ((null? ids) #f)
+                   ((bound-member (car ids) (cdr ids)) #t)
+                   (else (lp (cdr ids)))))
+           (syntax-violation '@bind "duplicate bound identifier" x)
+           (with-syntax (((old-v ...) (generate-temporaries #'(id ...)))
+                         ((v ...) (generate-temporaries #'(id ...))))
+             #'(let ((old-v id) ...
+                     (v val) ...)
+                 (dynamic-wind
+                   (lambda ()
+                     (set! id v) ...)
+                   (lambda () b0 b1 ...)
+                   (lambda ()
+                     (set! id old-v) ...)))))))))
+
+
 \f
 
 ;;; {Defmacros}
 (define (apply-to-args args fn) (apply fn args))
 
 (defmacro false-if-exception (expr)
-  `(catch #t (lambda () ,expr)
-         (lambda args #f)))
+  `(catch #t
+     (lambda ()
+       ;; avoid saving backtraces inside false-if-exception
+       (with-fluid* the-last-stack (fluid-ref the-last-stack)
+         (lambda () ,expr)))
+     (lambda args #f)))
 
 \f
 
 (set! %load-hook %load-announce)
 
 (define (load name . reader)
+  ;; 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 autocompilation is enabled, will try autocompilation, just
+  ;; as primitive-load-path does internally. primitive-load is
+  ;; unaffected. Returns #f if autocompilation failed or was disabled.
+  (define (autocompiled-file-name name)
+    (catch #t
+      (lambda ()
+        (let* ((cfn ((@ (system base compile) compiled-file-name) name))
+               (scmstat (stat name))
+               (gostat (stat cfn #f)))
+          (if (and gostat (= (stat:mtime gostat) (stat:mtime scmstat)))
+              cfn
+              (begin
+                (if gostat
+                    (format (current-error-port)
+                            ";;; note: source file ~a\n;;;       newer than compiled ~a\n"
+                            name cfn))
+                (cond
+                 (%load-should-autocompile
+                  (%warn-autocompilation-enabled)
+                  (format (current-error-port) ";;; compiling ~a\n" name)
+                  (let ((cfn ((@ (system base compile) compile-file) name
+                              #:env (current-module))))
+                    (format (current-error-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)
+        #f)))
   (with-fluid* current-reader (and (pair? reader) (car reader))
     (lambda ()
-      (start-stack 'load-stack
-                  (primitive-load name)))))
+      (let ((cfn (autocompiled-file-name name)))
+        (if cfn
+            (load-compiled cfn)
+            (start-stack 'load-stack
+                         (primitive-load name)))))))
 
 \f
 
 ;;; See the file `COPYING' for terms applying to this program.
 ;;;
 
-(define expt
-  (let ((integer-expt integer-expt))
-    (lambda (z1 z2)
-      (cond ((and (exact? z2) (integer? z2))
-            (integer-expt z1 z2))
-           ((and (real? z2) (real? z1) (>= z1 0))
-            ($expt z1 z2))
-           (else
-            (exp (* z2 (log z1))))))))
-
 (define (sinh z)
   (if (real? z) ($sinh z)
       (let ((x (real-part z)) (y (imag-part z)))
 ;; NOTE: This binding is used in libguile/modules.c.
 (define module-eval-closure (record-accessor module-type 'eval-closure))
 
-(define module-transformer (record-accessor module-type 'transformer))
+;; (define module-transformer (record-accessor module-type 'transformer))
 (define set-module-transformer! (record-modifier module-type 'transformer))
 ;; (define module-name (record-accessor module-type 'name)) wait until mods are booted
 (define set-module-name! (record-modifier module-type 'name))
       ;; Make it possible to lookup the module from the environment.
       ;; This implementation is correct since an eval closure can belong
       ;; to maximally one module.
-      (set-procedure-property! closure 'module module))))
+
+      ;; XXX: The following line introduces a circular reference that
+      ;; precludes garbage collection of modules with the current weak hash
+      ;; table semantics (see
+      ;; http://lists.gnu.org/archive/html/guile-devel/2009-01/msg00102.html and
+      ;; http://thread.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/2465
+      ;; for details).  Since it doesn't appear to be used (only in
+      ;; `scm_lookup_closure_module ()', which has 1 caller), we just comment
+      ;; it out.
+
+      ;(set-procedure-property! closure 'module module)
+      )))
 
 \f
 
       ;; Import the default set of bindings (from the SCM module) in MODULE.
       (module-use! module the-scm-module)))
 
+(define (make-fresh-user-module)
+  (let ((m (make-module)))
+    (beautify-user-module! m)
+    m))
+
 ;; NOTE: This binding is used in libguile/modules.c.
 ;;
 (define resolve-module
   (let ((accessor (record-accessor module-type 'name)))
     (lambda (mod)
       (or (accessor mod)
-          (begin
-            (set-module-name! mod (list (gensym)))
+          (let ((name (list (gensym))))
+            ;; Name MOD and bind it in THE-ROOT-MODULE so that it's visible
+            ;; to `resolve-module'.  This is important as `psyntax' stores
+            ;; module names and relies on being able to `resolve-module'
+            ;; them.
+            (set-module-name! mod name)
+            (nested-define! the-root-module `(%app modules ,@name) mod)
             (accessor mod))))))
 
 ;; (define-special-value '(%app modules new-ws) (lambda () (make-scm-module)))
@@ -2320,9 +2405,9 @@ module '(ice-9 q) '(make-q q-length))}."
 ;;;
 
 (defmacro define-option-interface (option-group)
-  (let* ((option-name car)
-        (option-value cadr)
-        (option-documentation caddr)
+  (let* ((option-name 'car)
+        (option-value 'cadr)
+        (option-documentation 'caddr)
 
         ;; Below follow the macros defining the run-time option interfaces.
 
@@ -2333,15 +2418,15 @@ module '(ice-9 q) '(make-q q-length))}."
                                   (,interface (car args)) (,interface))
                                  (else (for-each
                                          (lambda (option)
-                                           (display (option-name option))
+                                           (display (,option-name option))
                                            (if (< (string-length
-                                                   (symbol->string (option-name option)))
+                                                   (symbol->string (,option-name option)))
                                                   8)
                                                (display #\tab))
                                            (display #\tab)
-                                           (display (option-value option))
+                                           (display (,option-value option))
                                            (display #\tab)
-                                           (display (option-documentation option))
+                                           (display (,option-documentation option))
                                            (newline))
                                          (,interface #t)))))))
 
@@ -2538,8 +2623,6 @@ module '(ice-9 q) '(make-q q-length))}."
                 (apply make-stack #t save-stack primitive-eval #t 0 narrowing))
                ((load-stack)
                 (apply make-stack #t save-stack 0 #t 0 narrowing))
-               ((tk-stack)
-                (apply make-stack #t save-stack tk-stack-mark #t 0 narrowing))
                ((#t)
                 (apply make-stack #t save-stack 0 1 narrowing))
                (else
@@ -2618,11 +2701,14 @@ module '(ice-9 q) '(make-q q-length))}."
 ;;; The default repl-reader function.  We may override this if we've
 ;;; the readline library.
 (define repl-reader
-  (lambda (prompt)
+  (lambda (prompt . reader)
     (display (if (string? prompt) prompt (prompt)))
     (force-output)
     (run-hook before-read-hook)
-    ((or (fluid-ref current-reader) read) (current-input-port))))
+    ((or (and (pair? reader) (car reader))
+         (fluid-ref current-reader)
+         read)
+     (current-input-port))))
 
 (define (scm-style-repl)
 
@@ -2724,15 +2810,7 @@ module '(ice-9 q) '(make-q q-length))}."
                          (display ";;; QUIT executed, repl exitting")
                          (newline)
                          (repl-report)))
-                   args))
-
-          (-abort (lambda ()
-                    (if scm-repl-verbose
-                        (begin
-                          (display ";;; ABORT executed.")
-                          (newline)
-                          (repl-report)))
-                    (repl -read -eval -print))))
+                   args)))
 
     (let ((status (error-catching-repl -read
                                       -eval
@@ -2927,8 +3005,6 @@ module '(ice-9 q) '(make-q q-length))}."
     (process-use-modules (list (list ,@(compile-interface-spec spec))))
     *unspecified*))
 
-;; Dirk:FIXME:: This incorrect (according to R5RS) syntax needs to be changed
-;; as soon as guile supports hygienic macros.
 (define-syntax define-private
   (syntax-rules ()
     ((_ foo bar)
@@ -2950,6 +3026,13 @@ module '(ice-9 q) '(make-q q-length))}."
        (defmacro name args . body)
        (export-syntax name)))))
 
+;; And now for the most important macro.
+(define-syntax λ
+  (syntax-rules ()
+    ((_ formals body ...)
+     (lambda formals body ...))))
+
+\f
 ;; Export a local variable
 
 ;; This function is called from "modules.c".  If you change it, be
@@ -3166,6 +3249,7 @@ module '(ice-9 q) '(make-q q-length))}."
 (define %cond-expand-features
   ;; Adjust the above comment when changing this.
   '(guile
+    guile-2
     r5rs
     srfi-0   ;; cond-expand itself
     srfi-4   ;; homogenous numeric vectors
@@ -3190,69 +3274,66 @@ module '(ice-9 q) '(make-q q-length))}."
                     (append (hashq-ref %cond-expand-table mod '())
                             features)))))
 
-(define cond-expand
-  (procedure->memoizing-macro
-   (lambda (exp env)
-     (let ((clauses (cdr exp))
-          (syntax-error (lambda (cl)
-                          (error "invalid clause in `cond-expand'" cl))))
-       (letrec
-          ((test-clause
-            (lambda (clause)
-              (cond
-               ((symbol? clause)
-                (or (memq clause %cond-expand-features)
-                    (let lp ((uses (module-uses (env-module env))))
-                      (if (pair? uses)
-                          (or (memq clause
-                                    (hashq-ref %cond-expand-table
-                                               (car uses) '()))
-                              (lp (cdr uses)))
-                          #f))))
-               ((pair? clause)
-                (cond
-                 ((eq? 'and (car clause))
-                  (let lp ((l (cdr clause)))
-                    (cond ((null? l)
-                           #t)
-                          ((pair? l)
-                           (and (test-clause (car l)) (lp (cdr l))))
-                          (else
-                           (syntax-error clause)))))
-                 ((eq? 'or (car clause))
-                  (let lp ((l (cdr clause)))
-                    (cond ((null? l)
-                           #f)
-                          ((pair? l)
-                           (or (test-clause (car l)) (lp (cdr l))))
-                          (else
-                           (syntax-error clause)))))
-                 ((eq? 'not (car clause))
-                  (cond ((not (pair? (cdr clause)))
-                         (syntax-error clause))
-                        ((pair? (cddr clause))
-                         ((syntax-error clause))))
-                  (not (test-clause (cadr clause))))
-                 (else
-                  (syntax-error clause))))
-               (else
-                (syntax-error clause))))))
-        (let lp ((c clauses))
-          (cond
-           ((null? c)
-            (error "Unfulfilled `cond-expand'"))
-           ((not (pair? c))
-            (syntax-error c))
-           ((not (pair? (car c)))
-            (syntax-error (car c)))
-           ((test-clause (caar c))
-            `(begin ,@(cdar c)))
-           ((eq? (caar c) 'else)
-            (if (pair? (cdr c))
-                (syntax-error c))
-            `(begin ,@(cdar c)))
-           (else
-            (lp (cdr c))))))))))
+(define-macro (cond-expand . clauses)
+  (let ((syntax-error (lambda (cl)
+                        (error "invalid clause in `cond-expand'" cl))))
+    (letrec
+        ((test-clause
+          (lambda (clause)
+            (cond
+             ((symbol? clause)
+              (or (memq clause %cond-expand-features)
+                  (let lp ((uses (module-uses (current-module))))
+                    (if (pair? uses)
+                        (or (memq clause
+                                  (hashq-ref %cond-expand-table
+                                             (car uses) '()))
+                            (lp (cdr uses)))
+                        #f))))
+             ((pair? clause)
+              (cond
+               ((eq? 'and (car clause))
+                (let lp ((l (cdr clause)))
+                  (cond ((null? l)
+                         #t)
+                        ((pair? l)
+                         (and (test-clause (car l)) (lp (cdr l))))
+                        (else
+                         (syntax-error clause)))))
+               ((eq? 'or (car clause))
+                (let lp ((l (cdr clause)))
+                  (cond ((null? l)
+                         #f)
+                        ((pair? l)
+                         (or (test-clause (car l)) (lp (cdr l))))
+                        (else
+                         (syntax-error clause)))))
+               ((eq? 'not (car clause))
+                (cond ((not (pair? (cdr clause)))
+                       (syntax-error clause))
+                      ((pair? (cddr clause))
+                       ((syntax-error clause))))
+                (not (test-clause (cadr clause))))
+               (else
+                (syntax-error clause))))
+             (else
+              (syntax-error clause))))))
+      (let lp ((c clauses))
+        (cond
+         ((null? c)
+          (error "Unfulfilled `cond-expand'"))
+         ((not (pair? c))
+          (syntax-error c))
+         ((not (pair? (car c)))
+          (syntax-error (car c)))
+         ((test-clause (caar c))
+          `(begin ,@(cdar c)))
+         ((eq? (caar c) 'else)
+          (if (pair? (cdr c))
+              (syntax-error c))
+          `(begin ,@(cdar c)))
+         (else
+          (lp (cdr c))))))))
 
 ;; This procedure gets called from the startup code with a list of
 ;; numbers, which are the numbers of the SRFIs to be loaded on startup.