Synch with Oort Gnus.
[elisp/gnus.git-] / lisp / gnus-clfns.el
1 ;;; gnus-clfns.el --- compiler macros for emulating cl functions
2 ;; Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3
4 ;; Author: Kastsumi Yamaoka <yamaoka@jpl.org>
5 ;; Keywords: cl, compile
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;; Commentary:
25
26 ;; Avoid cl runtime functions for FSF Emacsen.
27
28 ;;; Code:
29
30 (if (featurep 'xemacs)
31     nil
32   (require 'cl)
33
34   (define-compiler-macro butlast (&whole form x &optional n)
35     (if (and (fboundp 'butlast)
36              (subrp (symbol-function 'butlast)))
37         form
38       (if n
39           `(let ((x ,x)
40                  (n ,n))
41              (if (and n (<= n 0))
42                  x
43                (let ((m (length x)))
44                  (or n (setq n 1))
45                  (and (< n m)
46                       (progn
47                         (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil))
48                         x)))))
49         `(let* ((x ,x)
50                 (m (length x)))
51            (and (< 1 m)
52                 (progn
53                   (setcdr (nthcdr (- m 2) x) nil)
54                   x))))))
55
56   (define-compiler-macro coerce (&whole form x type)
57     (if (and (fboundp 'coerce)
58              (subrp (symbol-function 'coerce)))
59         form
60       `(let ((x ,x)
61              (type ,type))
62          (cond ((eq type 'list) (if (listp x) x (append x nil)))
63                ((eq type 'vector) (if (vectorp x) x (vconcat x)))
64                ((eq type 'string) (if (stringp x) x (concat x)))
65                ((eq type 'array) (if (arrayp x) x (vconcat x)))
66                ((and (eq type 'character) (stringp x) (= (length x) 1))
67                 (aref x 0))
68                ((and (eq type 'character) (symbolp x)
69                      (= (length (symbol-name x)) 1))
70                 (aref (symbol-name x) 0))
71                ((eq type 'float) (float x))
72                ((typep x type) x)
73                (t (error "Can't coerce %s to type %s" x type))))))
74
75   (define-compiler-macro last (&whole form x &optional n)
76     (if (and (fboundp 'last)
77              (subrp (symbol-function 'last)))
78         form
79       (if n
80           `(let* ((x ,x)
81                   (n ,n)
82                   (m 0)
83                   (p x))
84              (while (consp p)
85                (incf m)
86                (pop p))
87              (if (<= n 0)
88                  p
89                (if (< n m)
90                    (nthcdr (- m n) x)
91                  x)))
92         `(let ((x ,x))
93            (while (consp (cdr x))
94              (pop x))
95            x))))
96
97   (define-compiler-macro merge (&whole form type seq1 seq2 pred &rest keys)
98     (if (and (fboundp 'merge)
99              (subrp (symbol-function 'merge)))
100         form
101       `(let ((type ,type)
102              (seq1 ,seq1)
103              (seq2 ,seq2)
104              (pred ,pred))
105          (or (listp seq1) (setq seq1 (append seq1 nil)))
106          (or (listp seq2) (setq seq2 (append seq2 nil)))
107          (let ((res nil))
108            (while (and seq1 seq2)
109              (if (funcall pred (car seq2) (car seq1))
110                  (push (pop seq2) res)
111                (push (pop seq1) res)))
112            (coerce (nconc (nreverse res) seq1 seq2) type)))))
113
114   (define-compiler-macro string (&whole form &rest args)
115     (if (and (fboundp 'string)
116              (subrp (symbol-function 'string)))
117         form
118       (list 'concat (cons 'list args))))
119
120   (define-compiler-macro subseq (&whole form seq start &optional end)
121     (if (and (fboundp 'subseq)
122              (subrp (symbol-function 'subseq)))
123         form
124       (if end
125           `(let ((seq ,seq)
126                  (start ,start)
127                  (end ,end))
128              (if (stringp seq)
129                  (substring seq start end)
130                (let (len)
131                  (if (< end 0)
132                      (setq end (+ end (setq len (length seq)))))
133                  (if (< start 0)
134                      (setq start (+ start (or len (setq len (length seq))))))
135                  (cond ((listp seq)
136                         (if (> start 0)
137                             (setq seq (nthcdr start seq)))
138                         (let ((res nil))
139                           (while (>= (setq end (1- end)) start)
140                             (push (pop seq) res))
141                           (nreverse res)))
142                        (t
143                         (let ((res (make-vector (max (- end start) 0) nil))
144                               (i 0))
145                           (while (< start end)
146                             (aset res i (aref seq start))
147                             (setq i (1+ i)
148                                   start (1+ start)))
149                           res))))))
150         `(let ((seq ,seq)
151                (start ,start))
152            (if (stringp seq)
153                (substring seq start)
154              (let (len)
155                (if (< start 0)
156                    (setq start (+ start (or len (setq len (length seq))))))
157                (cond ((listp seq)
158                       (if (> start 0)
159                           (setq seq (nthcdr start seq)))
160                       (copy-sequence seq))
161                      (t
162                       (let* ((end (or len (length seq)))
163                              (res (make-vector (max (- end start) 0) nil))
164                              (i 0))
165                         (while (< start end)
166                           (aset res i (aref seq start))
167                           (setq i (1+ i)
168                                 start (1+ start)))
169                         res)))))))))
170   )
171
172 (provide 'gnus-clfns)
173
174 ;;; gnus-clfns.el ends here