;;; -*- Mode:LISP; Package:INTERPRETER; Readtable:CL; Base:10; Lowercase:T -*- 
;;;
;;;
;;; INTERPRETER MACROS
;;;
;;; defun, defvar, defparameter, defconstant
;;;
;;; Something like this eventually belongs in SI: for use by the interpreter and
;;; the compiler.


(shadowing-import '(
		    k-lisp:defun
		    k-lisp:defvar
		    k-lisp:defparameter
		    k-lisp:defconstant
		    )
		  'interpreter)

;;; DEFUN
;;;
;;; (defun foo (args) body) does the following:
;;;
;;; Raises an error if foo is not a symbol.
;;;
;;; If the new evaluator is installed and active, puts #'(lambda (args) body) in the
;;; function cell of foo.  Using a closure rather than the text speeds up execution,
;;; especially of recursive functions, because the preprocessing is only done once.
;;;
;;; If the old evaluator is running, defun expands the way the old defun did, by calling
;;; si:process-defun-body and putting the result (text) in the function cell of foo.
;;; This definition, a named-lambda expression, will be properly handled by the new evaluator,
;;; if *ki-allow-apply-lambda-bagbiting* is T.
;;;
(defmacro defun (name lambda-list &body function-body)
  (cond ((not (symbolp name))
	 `(FERROR "~S is an invalid function identifier." ',name))
	((and (boundp 'user::*use-old-evaluator*) (not user::*use-old-evaluator*))
	 (multiple-value-bind (body declarations doc-string)
	     (si::gobble-declarations function-body t)
	   `(PROGN
	      (SETF (SYMBOL-FUNCTION ',name)
		    #'(INTERPRETER-NAMED-LAMBDA 
			,name ,lambda-list ,@declarations (BLOCK ,name ,@body)))
	      (SETF (DOCUMENTATION ',name :FUNCTION) ,doc-string)
	      ',name)))
	(t
	 `(progn
	    (fdefine ',name
		     (si::process-defun-body ',name '(,lambda-list . ,function-body))
		     t)
	    ',name))))


;;; DEFVAR
;;;
(defmacro defvar (si::name &optional (si::initial-value nil si::initial-value-supplied) si::documentation)
  `si::(PROGN (EVAL-WHEN (COMPILE LOAD EVAL)
	    (PROCLAIM-SPECIAL ',name))
	  (EVAL-WHEN (LOAD EVAL)
	    (WHEN (AND (NOT (BOUNDP ',name)) ,initial-value-supplied)
	      (SETF (SYMBOL-VALUE ',name) ,initial-value))
	    (SETF (DOCUMENTATION ',name :VARIABLE) ,documentation))
	  ',name))
	
(defmacro defvar-1 (&rest stuff)
  `(DEFVAR ,@stuff))


;;; DEFPARAMETER  
;;;
(defmacro defparameter (si::name si::initial-value &optional si::documentation)
  `si::(progn (eval-when (compile load eval)
	    (proclaim-special ',name))
	  (eval-when (load eval)
	    (setf (symbol-value ',name) ,initial-value)
	    (setf (documentation ',name :variable) ,documentation))
	  ',name))


;;; DEFCONSTANT
;;;
(defmacro defconstant (SI::name si::initial-value &optional documentation)
  `SI:(PROGN (EVAL-WHEN (COMPILE LOAD EVAL)
	    (PROCLAIM-SPECIAL (QUOTE ,name)))
	  (EVAL-WHEN (LOAD EVAL)
	    (LET ((NEW-VALUE ,initial-value))
	      (WHEN (BOUNDP (QUOTE ,name))
		(UNLESS (EQL NEW-VALUE (SYMBOL-VALUE (QUOTE ,name)))
		  (format *error-output* "~%WARNING:  Changing value of constant ~S" (QUOTE ,name))))
	      (SETF (SYMBOL-VALUE (QUOTE ,name)) NEW-VALUE)
	      (SETF (GET (QUOTE ,name) 'SYSTEM:SYSTEM-CONSTANT) T)
	      (SETF (DOCUMENTATION (QUOTE ,name) :VARIABLE) ,documentation)
	      (QUOTE ,name)))))

(defmacro defconst-1 (&rest stuff)
  `(DEFCONSTANT ,@stuff))


