;;; -*- Mode:LISP; Package:SYSTEM-INTERNALS; Readtable:CL; Base:10 -*-

;;;; maclisp braindamage --- very obsolete array-hackery

;;;; NOTE: Things like GET-LOCATIVE-POINTER-INTO-ARRAY are not in MACLISP.
;;;;       The person who wrote this stuff obviously doesnt know what he
;;;;       is talking about. (Listen up MLY!) Stupidly I have fixed stuff up
;;;;       that I needed for Macsyma, instead of shadowing and implementing a private
;;;;       copy of the winning (for the purpose) code.

;; fillarray, listarray should also be here -- except that the system uses them. FMH!

(defmacro array (x type &rest dimlist)
  "Obsolete Maclisp function for creating an array.  Don't use it."
  `(*array ',x ',type ,@dimlist))
(make-obsolete array "use MAKE-ARRAY")

(defun *array (x type &rest dimlist &aux array)
  "Obsolete Maclisp function for making an array.  Don't use it."
  (cond ((memq type '(readtable obarray))
	 (ferror "The array type ~S is not defined in Zetalisp" type))
	(t
	 (setq array
	       (zl:make-array dimlist :type (if (eq type 'flonum) 'art-float 'art-q)))
	 (if (eq type 'fixnum)
	     (fill-array array nil 0))
	 (cond ((null x)
		array)
	       ((symbolp x)
		(setf (symbol-function x) array)
		x)
	       (t
		(ferror "~S is not a legal first arg for ~S"
			x 'array))))))
(make-obsolete *array "use MAKE-ARRAY")


(defmacro get-locative-pointer-into-array (array-reference &environment env)
  "Similar to GET-LIST-POINTER-INTO-ARRAY except that it returns a
locative and doesn't require the array to be ART-Q-LIST.
Use LOCF of AREF instead of this in new programs."
  (let* ((arraycall (macroexpand array-reference env)))
    (case (car arraycall)
      (funcall `(locf (aref ,(cadr arraycall) . ,(cddr arraycall))))
      (arraycall `(locf (aref ,(caddr arraycall) . ,(cdddr arraycall))))
      ((apply funcall* apply)
       `(apply #'aloc ,(cadr arraycall) . ,(cddr arraycall)))
      (t `(locf (aref (symbol-function ,(car arraycall)) . ,(cdr arraycall)))))))
(make-obsolete get-locative-pointer-into-array "use LOCF and AREF instead")


(defmacro get-list-pointer-into-array (array-reference-form &environment env)
  "A Maclisp-compatibility function that returns a list pointer to part of an ART-Q-LIST
array.  This should not be used in new programs, use G-L-P and list decomposition
operations instead.  This function is not fully Maclisp-compatible in that the
array-reference form determines the starting element, not the last element referenced
by array invocation."
  (let ((reference (macroexpand array-reference-form env)))
    (case (car reference)
      (funcall
       `(make-list-pointer-to-array-element ,(cadr reference) ,@(cddr reference)))
      ((apply lexpr-funcall)
       `(apply #'make-list-pointer-to-array-element ,(cadr reference) ,@(cddr reference)))
      (otherwise
       `(make-list-pointer-to-array-element (function ,(car reference)) ,@(cdr reference))))))
(make-obsolete get-list-pointer-into-array "use G-L-P and list operations instead")

(defun make-list-pointer-to-array-element (&rest args)
  "An auxiliary routine for GET-LIST-POINTER-INTO-ARRAY. Like ALOC but returns a list pointer."
  (declare (arglist array &rest subscripts))
  (%make-pointer dtp-list (apply #'aloc args)))

(defmacro arraycall (ignore array &rest dims)
  `(funcall ,array . ,dims))

(defun arraydims (array &aux type)
  "Return a list of the array-type and dimensions of ARRAY.
This is an obsolete Maclisp function."
  (and (symbolp array) (setq array (symbol-function array)))
  (check-type array array)
	;SHOULD CHECK FOR INVZ
  (setq type (nth (%p-ldb-offset %%array-type-field array 0) array-types))
  (cons type (array-dimensions array)))


;;;; Store
;;; Copyright (c) Jan 1984 by Glenn S. Burke and Massachusetts Institute of Technology.
;;; GSB's new version of STORE in NIL is not maclisp compatible.
;;; So dont inflict it on the lispmachine. I have put back my correct maclisp
;;; compatible version.


;(DEFMACRO STORE (ARRAY-REFERENCE VALUE)
;  (LET* ((ARRAYCALL (MACROEXPAND ARRAY-REFERENCE)))
;    (CASE (CAR ARRAYCALL)
;      (FUNCALL `(ASET ,VALUE ,(CADR ARRAYCALL) . ,(CDDR ARRAYCALL)))
;      (ARRAYCALL `(ASET ,VALUE ,(CADDR ARRAYCALL) . ,(CDDDR ARRAYCALL)))
;      ((APPLY FUNCALL* APPLY)
;       `(APPLY #'ASET ,VALUE ,(CADR ARRAYCALL) . ,(CDDR ARRAYCALL)))
;      (T `(ASET ,VALUE (FUNCTION ,(CAR ARRAYCALL)) . ,(CDR ARRAYCALL))))))

;(defmacro store (array-form value &environment env)
;  (let* ((inversions '((zl:aref . aset)
;		       (cl:aref . aset)
;		       (char . aset)
;		       (bit . aset)
;		       (sbit . aset)
;		       (svref . aset)
;		       (schar . aset)
;		       (funcall . maclisp-store-hack)))
;	 (foo (macroexpand array-form env))
;	 (invert (and (consp foo)
;		      (symbolp (car foo))
;		      (cdr (assq (car foo) inversions))))
;	 (tem nil))
;    (cond ((not (null invert)) `(,invert ,value ,@(cdr foo)))
;	  ((and (consp foo) (symbolp (car foo)))
;	   (cond ((not (memq (car foo) '(apply lexpr-funcall)))
;		  `(maclisp-store-hack ,value ',(car foo) ,@(cdr foo)))
;		 ((and (consp (setq tem (macroexpand (cadr foo) env)))
;		       (memq (car tem) '(quote function))
;		       (setq tem (cdr (assq (cadr tem) inversions))))
;		  `(apply #',tem ,value ,@(cddr array-form)))
;		 (t `(apply #'maclisp-store-hack ,value ,@(cdr foo)))))
;	  (t
;	   (ferror "The array reference form ~S in not understood by ~S"
;		   array-form 'store)))))


;(defun maclisp-store-hack (value frob &rest subscripts &aux tem)
;  (do-forever
;    (etypecase frob
;      (array (return (apply #'aset value frob subscripts)))
;      (symbol (and (fboundp frob)
;		   (typep (setq tem (symbol-function frob)) 'array)
;		   (return (apply #'aset value tem subscripts)))))))

(DEFMACRO STORE (ARRAY-REFERENCE VALUE)
  "STORE: Maclisp compatible for all but the most obscure unreasonable usages"
  ;; YOU SEE. ANY TIME YOU DO AN ARRAY REFERENCE IN MACLISP THE
  ;; ACTUALLY ADDRESS (SORT OF A LOCATIVE) OF THE VALUE THAT WAS ACCESSED
  ;; ENDS UP IN PDP-10 REGISTER TT (OR WAS IT T?). STORE IS THEN EASY TO
  ;; IMPLEMENT, HENCE THE RIGHT TO LEFT EVALUATION ORDER, VALUE FIRST,
  ;; THEN THE ARRAY-REFERENCE FORM. AT SOME TIME THE CADR/LISPM SOFTWARE
  ;; HAD SIMILAR REGISTERS (IN THE MICROCODE) AND SIMILIAR IMPLEMENTATION
  ;; DETAILS FOR STORE. THIS DEFINITION AS A MACRO FOLLOWS WHAT
  ;; WAS NEEDED TO BRING UP MACSYMA IN VAX-NIL.
  (LET* ((ARRAYCALL (MACROEXPAND ARRAY-REFERENCE)))
    (SELECTQ (CAR ARRAYCALL)
      (FUNCALL `(ASET ,VALUE (STORE-MEDIATION-ROUTINE-INTERNAL ,(CADR ARRAYCALL))
		      ,@(CDDR ARRAYCALL)))
      (ARRAYCALL `(ASET ,VALUE ,(CADDR ARRAYCALL)  ,@(CDDDR ARRAYCALL)))
      ((LEXPR-FUNCALL FUNCALL* APPLY)
       `(LEXPR-FUNCALL 'ASET ,VALUE (STORE-MEDIATION-ROUTINE-INTERNAL ,(CADR ARRAYCALL))
		       ,@(CDDR ARRAYCALL)))
      (T
       ;; THIS IS CORRECT IFF (CAR ARRAYCALL) IS THE ACTUAL ARRAY.
       ;; IF IT WAS THE OBSCURE USAGE OF A GENERAL FUNCTION CALL THAT
       ;; DOES SOME ARRAY REFERENCE, THEREBY LEAVING REGISTER "TT" IN
       ;; A CERTAIN STATE, THEN WE WILL LOSE.
       ;; IF WE TOOK SERIOUSLY THE MACLISP (DECLARE (ARRAY ...)) FORM
       ;; THEN AT LEAST WE WOULD KNOW AS MUCH AS WHAT THE USER INTENDED
       ;; TO TELL THE MACLISP COMPILER IN DAYS PAST. THAT NOT BEING THE
       ;; CASE, HE WILL GET SOME OTHER WARNING, PERHAPS.
       ;; NOTE WELL: Even though it is possible on the LISPM to have a function
       ;; cell contain a symbol (which may also be an array) it is NOT POSSIBLE
       ;; IN MACLISP to have this sort of indefinite indirection in the case
       ;; of the ARRAY property. (Although it is in the case of EXPR property).
       `(ASET ,VALUE (FUNCTION ,(CAR ARRAYCALL))  ,@(CDR ARRAYCALL))))))



(DEFUN STORE-MEDIATION-ROUTINE-INTERNAL (X)
  (DO ((Y X (COND ((SYMBOLP Y)
		   (FSYMEVAL Y))
		  ('ELSE
		   ;; NOTE USE OF UPPER CASE ERROR MESSAGE IN MACLISP STYLE
		   (FERROR NIL "CAN'T GET ARRAY POINTER FOR: ~S" X)))))
      ((ARRAYP Y) Y)))


