* pym.el (defun-maybe): Use `defalias' instead of `defun';
authoryamaoka <yamaoka>
Mon, 29 Jul 2002 10:46:13 +0000 (10:46 +0000)
committeryamaoka <yamaoka>
Mon, 29 Jul 2002 10:46:13 +0000 (10:46 +0000)
 don't handle `current-load-list';
 always return a function symbol.
(defmacro-maybe): Set a symbol to a macro definition itself;
 don't handle `current-load-list';
 always return a macro symbol.
(defsubst-maybe): Set a symbol to a function definition itself;
 don't handle `current-load-list';
 always return a function symbol.
(defalias-maybe): Always return a new definition.
(defvar-maybe): Always return a variable symbol.
(defconst-maybe): Ditto.
(defun-maybe-cond): Use `defalias' instead of `defun';
 don't handle `current-load-list';
 always return a function symbol.
(defmacro-maybe-cond): Set a symbol to a macro definition itself;
 don't handle `current-load-list';
 always return a macro symbol.
(defsubst-maybe-cond): Set a symbol to a function definition itself;
 don't handle `current-load-list';
 always return a function symbol.
(defun-when-void): Always return a function symbol.
(defmacro-when-void): New macro.
(defsubst-when-void): New macro.
(defalias-when-void): New macro.
(defvar-when-void): New macro.
(defconst-maybe): New macro.

ChangeLog
pym.el

index 1b50a8e..eab8117 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,43 @@
+2002-07-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * pym.el (defun-maybe): Use `defalias' instead of `defun'; don't
+       handle `current-load-list'; always return a function symbol.
+       (defmacro-maybe): Set a symbol to a macro definition itself; don't
+       handle `current-load-list'; always return a macro symbol.
+       (defsubst-maybe): Set a symbol to a function definition itself;
+       don't handle `current-load-list'; always return a function symbol.
+       (defalias-maybe): Always return a new definition.
+       (defvar-maybe): Always return a variable symbol.
+       (defconst-maybe): Ditto.
+       (defun-maybe-cond): Use `defalias' instead of `defun'; don't
+       handle `current-load-list'; always return a function symbol.
+       (defmacro-maybe-cond): Set a symbol to a macro definition itself;
+       don't handle `current-load-list'; always return a macro symbol.
+       (defsubst-maybe-cond): Set a symbol to a function definition
+       itself; don't handle `current-load-list'; always return a function
+       symbol.
+       (defun-when-void): Always return a function symbol.
+       (defmacro-when-void): New macro.
+       (defsubst-when-void): New macro.
+       (defalias-when-void): New macro.
+       (defvar-when-void): New macro.
+       (defconst-maybe): New macro.
+
+2002-07-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * pym.el (defun-maybe): Doc fix.
+       (defun-when-void): New macro.
+
+2002-07-24  Shuhei KOBAYASHI  <shuhei@aqua.ocn.ne.jp>
+
+       * pym.el (def*-maybe-enable-compile-time-hack): New variable;
+       default to nil.
+       (defun-maybe): Use it.
+
 2002-07-13  Daiki Ueno  <daiki@xemacs.org>
 
        * mcs-xm.el (encode-mime-charset-string): Use `defun' instead of
-       `defsubst'
+       `defsubst'.
 
 2002-07-10  Adrian Aichner  <adrian@xemacs.org>
 
diff --git a/pym.el b/pym.el
index c895ef2..11c70bb 100644 (file)
--- a/pym.el
+++ b/pym.el
@@ -1,9 +1,11 @@
-;;; pym.el --- Macros for Your Poe.
+;;; pym.el --- Macros for Your Poe
 
-;; Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002
+;; Free Software Foundation, Inc.
 
 ;; Author: MORIOKA Tomohiko <tomo@m17n.org>
 ;;     Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;;     Katsumi Yamaoka  <yamaoka@jpl.org>
 ;; Keywords: byte-compile, evaluation, edebug, internal
 
 ;; This file is part of APEL (A Portable Emacs Library).
 
 ;;; Code:
 
-;; for `load-history'.
-(or (boundp 'current-load-list) (setq current-load-list nil))
-
 (require 'static)
 
 
 ;;; Conditional define.
 
+(defvar def*-maybe-enable-compile-time-hack nil
+  "If non-nil, `def*-maybe' macros will do compile-time check.
+`def*-maybe' macro normally checks existence of its target function or
+variable at load-time.  But if this variable is non-nil at compile-time,
+existence of its target is first checked at compile-time, and if exists,
+it will emit no compiled code at all!
+You should set this variable to non-nil only when you really know what
+you are doing.")
+
 (put 'defun-maybe 'lisp-indent-function 'defun)
 (defmacro defun-maybe (name &rest everything-else)
   "Define NAME as a function if NAME is not defined.
-See also the function `defun'."
-  (or (and (fboundp name)
-          (not (get name 'defun-maybe)))
-      (` (or (fboundp (quote (, name)))
-            (prog1
-                (defun (, name) (,@ everything-else))
-              ;; This `defun' will be compiled to `fset',
-              ;; which does not update `load-history'.
-              ;; We must update `current-load-list' explicitly.
-              (setq current-load-list
-                    (cons (quote (, name)) current-load-list))
-              (put (quote (, name)) 'defun-maybe t))))))
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.  In order to always
+check for the existence of NAME, use `defun-when-void' instead.  See
+also the function `defun'."
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (fboundp name))
+         (get name 'defun-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (prog1
+              (, qname)
+            (if (not (fboundp (, qname)))
+                (progn
+                  ;; Use `defalias' to update `load-history'.
+                  (defalias (, qname)
+                    (function (lambda (,@ everything-else))))
+                  (put (, qname) 'defun-maybe t))))))))
 
 (put 'defmacro-maybe 'lisp-indent-function 'defun)
 (defmacro defmacro-maybe (name &rest everything-else)
   "Define NAME as a macro if NAME is not defined.
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.  In order to always
+check for the existence of NAME, use `defmacro-when-void' instead.
 See also the function `defmacro'."
-  (or (and (fboundp name)
-          (not (get name 'defmacro-maybe)))
-      (` (or (fboundp (quote (, name)))
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (fboundp name))
+         (get name 'defmacro-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (if (fboundp (, qname))
+              (, qname)
             (prog1
                 (defmacro (, name) (,@ everything-else))
-              ;; This `defmacro' will be compiled to `fset',
-              ;; which does not update `load-history'.
-              ;; We must update `current-load-list' explicitly.
-              (setq current-load-list
-                    (cons (quote (, name)) current-load-list))
-              (put (quote (, name)) 'defmacro-maybe t))))))
+              ;; Use `defalias' to update `load-history'.
+              (defalias (, qname) (symbol-function (, qname)))
+              (put (, qname) 'defmacro-maybe t)))))))
 
 (put 'defsubst-maybe 'lisp-indent-function 'defun)
 (defmacro defsubst-maybe (name &rest everything-else)
   "Define NAME as an inline function if NAME is not defined.
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.  In order to always
+check for the existence of NAME, use `defsubst-when-void' instead.
 See also the macro `defsubst'."
-  (or (and (fboundp name)
-          (not (get name 'defsubst-maybe)))
-      (` (or (fboundp (quote (, name)))
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (fboundp name))
+         (get name 'defsubst-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (if (fboundp (, qname))
+              (, qname)
             (prog1
                 (defsubst (, name) (,@ everything-else))
-              ;; This `defsubst' will be compiled to `fset',
-              ;; which does not update `load-history'.
-              ;; We must update `current-load-list' explicitly.
-              (setq current-load-list
-                    (cons (quote (, name)) current-load-list))
-              (put (quote (, name)) 'defsubst-maybe t))))))
+              ;; Use `defalias' to update `load-history'.
+              (defalias (, qname) (symbol-function (, qname)))
+              (put (, qname) 'defsubst-maybe t)))))))
 
 (defmacro defalias-maybe (symbol definition)
   "Define SYMBOL as an alias for DEFINITION if SYMBOL is not defined.
+Note that it will never produce a byte-compiled code when SYMBOL has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.  In order to always
+check for the existence of SYMBOL, use `defalias-when-void' instead.
 See also the function `defalias'."
   (setq symbol (eval symbol))
-  (or (and (fboundp symbol)
-          (not (get symbol 'defalias-maybe)))
-      (` (or (fboundp (quote (, symbol)))
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (fboundp symbol))
+         (get symbol 'defalias-maybe))
+      (let ((qsymbol (` (quote (, symbol)))))
+       (` (if (fboundp (, qsymbol))
+              (symbol-function (, qsymbol))
             (prog1
-                (defalias (quote (, symbol)) (, definition))
-              ;; `defalias' updates `load-history' internally.
-              (put (quote (, symbol)) 'defalias-maybe t))))))
+                ;; `defalias' updates `load-history' internally.
+                (defalias (, qsymbol) (, definition))
+              (put (, qsymbol) 'defalias-maybe t)))))))
 
 (defmacro defvar-maybe (name &rest everything-else)
   "Define NAME as a variable if NAME is not defined.
-See also the function `defvar'."
-  (or (and (boundp name)
-          (not (get name 'defvar-maybe)))
-      (` (or (boundp (quote (, name)))
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.  In order to always
+check for the existence of NAME, use `defvar-when-void' instead.  See
+also the function `defvar'."
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (boundp name))
+         (get name 'defvar-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (if (boundp (, qname))
+              (, qname)
             (prog1
+                ;; byte-compiler will generate code to update
+                ;; `load-history'.
                 (defvar (, name) (,@ everything-else))
-              ;; byte-compiler will generate code to update
-              ;; `load-history'.
-              (put (quote (, name)) 'defvar-maybe t))))))
+              (put (, qname) 'defvar-maybe t)))))))
 
 (defmacro defconst-maybe (name &rest everything-else)
   "Define NAME as a constant variable if NAME is not defined.
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.  In order to always
+check for the existence of NAME, use `defconst-when-void' instead.
 See also the function `defconst'."
-  (or (and (boundp name)
-          (not (get name 'defconst-maybe)))
-      (` (or (boundp (quote (, name)))
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (boundp name))
+         (get name 'defconst-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (if (boundp (, qname))
+              (, qname)
             (prog1
+                ;; byte-compiler will generate code to update
+                ;; `load-history'.
                 (defconst (, name) (,@ everything-else))
-              ;; byte-compiler will generate code to update
-              ;; `load-history'.
-              (put (quote (, name)) 'defconst-maybe t))))))
+              (put (, qname) 'defconst-maybe t)))))))
 
 (defmacro defun-maybe-cond (name args &optional doc &rest clauses)
   "Define NAME as a function if NAME is not defined.
-CLAUSES are like those of `cond' expression, but each condition is evaluated
-at compile-time and, if the value is non-nil, the body of the clause is used
-for function definition of NAME.
-See also the function `defun'."
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.
+CLAUSES are like those of `cond' expression, but each condition is
+evaluated at compile-time and, if the value is non-nil, the body of
+the clause is used for function definition of NAME.  See also the
+function `defun'."
   (or (stringp doc)
       (setq clauses (cons doc clauses)
            doc nil))
-  (or (and (fboundp name)
-          (not (get name 'defun-maybe)))
-      (` (or (fboundp (quote (, name)))
-            (prog1
-                (static-cond
-                 (,@ (mapcar
-                      (function
-                       (lambda (case)
-                         (list (car case)
-                               (if doc
-                                   (` (defun (, name) (, args)
-                                        (, doc)
-                                        (,@ (cdr case))))
-                                 (` (defun (, name) (, args)
-                                      (,@ (cdr case))))))))
-                      clauses)))
-              ;; This `defun' will be compiled to `fset',
-              ;; which does not update `load-history'.
-              ;; We must update `current-load-list' explicitly.
-              (setq current-load-list
-                    (cons (quote (, name)) current-load-list))
-              (put (quote (, name)) 'defun-maybe t))))))
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (fboundp name))
+         (get name 'defun-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (prog1
+              (, qname)
+            (if (not (fboundp (, qname)))
+                (progn
+                  (static-cond
+                   (,@ (mapcar
+                        (function
+                         (lambda (case)
+                           (list (car case)
+                                 (if doc
+                                     (` (defalias (, qname)
+                                          (function
+                                           (lambda (, args)
+                                             (, doc)
+                                             (,@ (cdr case))))))
+                                   (` (defalias (, qname)
+                                        (function
+                                         (lambda (, args)
+                                           (,@ (cdr case))))))))))
+                        clauses)))
+                  (put (, qname) 'defun-maybe t))))))))
 
 (defmacro defmacro-maybe-cond (name args &optional doc &rest clauses)
   "Define NAME as a macro if NAME is not defined.
-CLAUSES are like those of `cond' expression, but each condition is evaluated
-at compile-time and, if the value is non-nil, the body of the clause is used
-for macro definition of NAME.
-See also the function `defmacro'."
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.
+CLAUSES are like those of `cond' expression, but each condition is
+evaluated at compile-time and, if the value is non-nil, the body of
+the clause is used for macro definition of NAME.  See also the
+function `defmacro'."
   (or (stringp doc)
       (setq clauses (cons doc clauses)
            doc nil))
-  (or (and (fboundp name)
-          (not (get name 'defmacro-maybe)))
-      (` (or (fboundp (quote (, name)))
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (fboundp name))
+         (get name 'defmacro-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (if (fboundp (, qname))
+              (, qname)
             (prog1
                 (static-cond
                  (,@ (mapcar
@@ -192,31 +246,38 @@ See also the function `defmacro'."
                        (lambda (case)
                          (list (car case)
                                (if doc
-                                   (` (defmacro (, name) (, args)
-                                        (, doc)
-                                        (,@ (cdr case))))
-                                 (` (defmacro (, name) (, args)
-                                      (,@ (cdr case))))))))
+                                   (` (prog1
+                                          (defmacro (, name) (, args)
+                                            (, doc)
+                                            (,@ (cdr case)))
+                                        (defalias (, qname)
+                                          (symbol-function (, qname)))))
+                                 (` (prog1
+                                        (defmacro (, name) (, args)
+                                          (,@ (cdr case)))
+                                      (defalias (, qname)
+                                        (symbol-function (, qname)))))))))
                       clauses)))
-              ;; This `defmacro' will be compiled to `fset',
-              ;; which does not update `load-history'.
-              ;; We must update `current-load-list' explicitly.
-              (setq current-load-list
-                    (cons (quote (, name)) current-load-list))
-              (put (quote (, name)) 'defmacro-maybe t))))))
+              (put (, qname) 'defmacro-maybe t)))))))
 
 (defmacro defsubst-maybe-cond (name args &optional doc &rest clauses)
   "Define NAME as an inline function if NAME is not defined.
-CLAUSES are like those of `cond' expression, but each condition is evaluated
-at compile-time and, if the value is non-nil, the body of the clause is used
-for function definition of NAME.
-See also the macro `defsubst'."
+Note that it will never produce a byte-compiled code when NAME has
+already been defined at the compile-time and the value for
+`def*-maybe-enable-compile-time-hack' is non-nil.
+CLAUSES are like those of `cond' expression, but each condition is
+evaluated at compile-time and, if the value is non-nil, the body of
+the clause is used for function definition of NAME.  See also the
+macro `defsubst'."
   (or (stringp doc)
       (setq clauses (cons doc clauses)
            doc nil))
-  (or (and (fboundp name)
-          (not (get name 'defsubst-maybe)))
-      (` (or (fboundp (quote (, name)))
+  (if (or (null def*-maybe-enable-compile-time-hack)
+         (not (fboundp name))
+         (get name 'defsubst-maybe))
+      (let ((qname (` (quote (, name)))))
+       (` (if (fboundp (, qname))
+              (, qname)
             (prog1
                 (static-cond
                  (,@ (mapcar
@@ -224,18 +285,91 @@ See also the macro `defsubst'."
                        (lambda (case)
                          (list (car case)
                                (if doc
-                                   (` (defsubst (, name) (, args)
-                                        (, doc)
-                                        (,@ (cdr case))))
-                                 (` (defsubst (, name) (, args)
-                                      (,@ (cdr case))))))))
+                                   (` (prog1
+                                          (defsubst (, name) (, args)
+                                            (, doc)
+                                            (,@ (cdr case)))
+                                        (defalias (, qname)
+                                          (symbol-function (, qname)))))
+                                 (` (prog1
+                                        (defsubst (, name) (, args)
+                                          (,@ (cdr case)))
+                                      (defalias (, qname)
+                                        (symbol-function (, qname)))))))))
                       clauses)))
-              ;; This `defsubst' will be compiled to `fset',
-              ;; which does not update `load-history'.
-              ;; We must update `current-load-list' explicitly.
-              (setq current-load-list
-                    (cons (quote (, name)) current-load-list))
-              (put (quote (, name)) 'defsubst-maybe t))))))
+              (put (, qname) 'defsubst-maybe t)))))))
+
+
+;;; Conditional define (always do load-time check).
+
+(put 'defun-when-void 'lisp-indent-function 'defun)
+(defmacro defun-when-void (name &rest everything-else)
+  "Define NAME as a function if NAME is not defined at the load-time.
+See also the function `defun' and the macro `defun-maybe'.  Note that
+the macro with the same name in XEmacs will be replaced with it."
+  (let ((qname (` (quote (, name)))))
+    (` (prog1
+          (, qname)
+        (if (not (fboundp (, qname)))
+            ;; Use `defalias' to update `load-history'.
+            (defalias (, qname)
+              (function (lambda (,@ everything-else)))))))))
+
+(put 'defmacro-when-void 'lisp-indent-function 'defun)
+(defmacro defmacro-when-void (name &rest everything-else)
+  "Define NAME as a macro if NAME is not defined at the load-time.
+See also the function `defmacro' and the macro `defmacro-maybe'."
+  (let ((qname (` (quote (, name)))))
+    (` (if (fboundp (, qname))
+          (, qname)
+        (prog1
+            (defmacro (, name) (,@ everything-else))
+          ;; Use `defalias' to update `load-history'.
+          (defalias (, qname) (symbol-function (, qname))))))))
+
+(put 'defsubst-when-void 'lisp-indent-function 'defun)
+(defmacro defsubst-when-void (name &rest everything-else)
+  "Define NAME as an inline function if NAME is not defined at the
+load-time.  See also the macros `defsubst' and `defsubst-maybe'."
+  (let ((qname (` (quote (, name)))))
+    (` (if (fboundp (, qname))
+          (, qname)
+        (prog1
+            (defsubst (, name) (,@ everything-else))
+          ;; Use `defalias' to update `load-history'.
+          (defalias (, qname) (symbol-function (, qname))))))))
+
+(defmacro defalias-when-void (symbol definition)
+  "Define SYMBOL as an alias for DEFINITION if SYMBOL is not defined at
+the load-time.  See also the function `defalias' and the macro
+`defalias-maybe'."
+  (let* ((symbol (eval symbol))
+        (qsymbol (` (quote (, symbol)))))
+    (` (if (fboundp (, qsymbol))
+          (symbol-function (, qsymbol))
+        ;; `defalias' updates `load-history' internally.
+        (defalias (, qsymbol) (, definition))))))
+
+(defmacro defvar-when-void (name &rest everything-else)
+  "Define NAME as a variable if NAME is not defined at the load-time.
+See also the function `defvar' and the macro `defvar-maybe'."
+  (let ((qname (` (quote (, name)))))
+    (` (if (boundp (, qname))
+          (, qname)
+        ;; byte-compiler will generate code to update
+        ;; `load-history'.
+        (defvar (, name) (,@ everything-else))))))
+
+(defmacro defconst-when-void (name &rest everything-else)
+  "Define NAME as a constant variable if NAME is not defined at the
+load-time.  See also the function `defconst' and the macro
+`defconst-maybe'."
+  (let ((qname (` (quote (, name)))))
+    (` (if (boundp (, qname))
+          (, qname)
+        ;; byte-compiler will generate code to update
+        ;; `load-history'.
+        (defconst (, name) (,@ everything-else))))))
 
 
 ;;; Edebug spec.