;;; liece-clfns.el --- compiler macros for emulating cl functions
;; Copyright (C) 1998-2000 Daiki Ueno

;; Author: Daiki Ueno <ueno@unixuser.org>
;; Created: 2000-03-19
;; Keywords: cl, compile

;; This file is part of Liece.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.


;;; Commentary:

;; This file is borrowed from `gnus-clfns.el' from T-gnus.
;; Avoid cl runtime functions for FSF Emacsen.

;;; Code:

(defun liece-clfns-subr-fboundp (symbol)
  "Return t if SYMBOL's function definition is a basic function."
  (and (fboundp symbol)
       (or (subrp (symbol-function symbol))
	   (and (fboundp 'symbol-file)
		(string-equal (symbol-file symbol) "subr")))))

(if (featurep 'xemacs)
    nil
  (require 'cl)

  (define-compiler-macro last (&whole form x &optional n)
    (if (liece-clfns-subr-fboundp 'last)
	form
      (if n
	  `(let* ((x ,x) (n ,n) (m 0) (p x))
	     (while (consp p)
	       (incf m)
	       (pop p))
	     (if (<= n 0)
		 p
	       (if (< n m)
		   (nthcdr (- m n) x)
		 x)))
	`(let ((x ,x))
	   (while (consp (cdr x))
	     (pop x))
	   x))))

  (define-compiler-macro remq (&whole form elt list)
    (if (liece-clfns-subr-fboundp 'remq)
	form
      `(let ((elt ,elt)
	     (list ,list))
	 (if (memq elt list)
	     (delq elt (copy-sequence list))
	   list))))

  (define-compiler-macro member-if (&whole form pred list)
    (if (liece-clfns-subr-fboundp 'member-if)
	form
      `(let ((fn ,pred)
	     (seq ,list))
	 (while (and seq (not (funcall fn (car seq))))
	   (pop seq))
	 seq)))

  (define-compiler-macro member-if-not (&whole form pred list)
    (if (liece-clfns-subr-fboundp 'member-if-not)
	form
      `(let ((fn ,pred)
	     (seq ,list))
	 (while (and seq (funcall fn (car seq)))
	   (pop seq))
	 seq)))
  
  (define-compiler-macro delete-if (&whole form pred list)
    (if (liece-clfns-subr-fboundp 'delete-if)
	form
      `(let* ((fn ,pred) (seq ,list) (p seq))
	 (while (and p (not (funcall fn (car p))))
	   (pop p))
	 (if p (delq (car p) seq)))))

  (define-compiler-macro remove-if (&whole form pred list)
    (if (liece-clfns-subr-fboundp 'remove-if)
	form
      `(let* ((fn ,pred) (seq (copy-sequence ,list)) (p seq))
	 (while (and p (not (funcall fn (car p))))
	   (pop p))
	 (if p (delq (car p) seq) seq))))

  (define-compiler-macro remove-if-not (&whole form pred list)
    (if (liece-clfns-subr-fboundp 'remove-if-not)
	form
      `(let* ((fn ,pred) (seq (copy-sequence ,list)) (p seq))
	 (while (and p (funcall fn (car p)))
	   (pop p))
	 (if p (delq (car p) seq) seq))))

  (define-compiler-macro assoc-if (&whole form pred list)
    (if (liece-clfns-subr-fboundp 'assoc-if)
	form
      `(let ((fn ,pred) (seq ,list))
	 (while (and seq (not (funcall fn (caar seq))))
	   (pop seq))
	 (car seq))))

  (define-compiler-macro rassoc-if (&whole form pred list)
    (if (liece-clfns-subr-fboundp 'rassoc-if)
	form
      `(let ((fn ,pred) (seq ,list))
	 (while (and seq (not (funcall fn (cdar seq))))
	   (pop seq))
	 (car seq)))))

(provide 'liece-clfns)

;;; liece-clfns.el ends here
