;;; -*- Mode:Lisp; Package:(NC LISP); Readtable:CL; Base:10 -*- ;;;; Rewriters (defrewrite not (x) `(if ,x nil t)) (defmacro def-n-arg-fcn (name rest 2-arg-fcn 0-arg-form 1-arg-form) `(defrewrite ,name (&rest ,rest) (cond ((null ,rest) ,0-arg-form) ((null (cdr ,rest)) ,1-arg-form) (t (do ((args (cdr ,rest) (cdr args)) (form (car ,rest) `(,',2-arg-fcn ,form ,(car args)))) ((null args) form)))))) (def-n-arg-fcn + numbers 2-arg-+ 0 (car numbers)) (def-n-arg-fcn - numbers 2-arg-- `(error "0 arg minus") `(2-arg-- 0 ,(car numbers))) (def-n-arg-fcn * numbers new-math::multiply-generic 1 (car numbers)) (def-n-arg-fcn / numbers new-math::divide-generic `(error "0 arg divide") `(new-math::divide-generic 1 (car numbers))) (def-n-arg-fcn logior numbers 2-arg-logior 0 (car numbers)) (def-n-arg-fcn logand numbers 2-arg-logand -1 (car numbers)) (def-n-arg-fcn logxor numbers 2-arg-logxor 0 (car numbers)) (def-n-arg-fcn logeqv numbers 2-arg-logxnor -1 (car numbers)) (defrewrite lognot (x) `(logxor -1 ,x)) (defrewrite lognand (x y) `(lognot (logand ,x ,y))) (defrewrite lognor (x y) `(lognot (logior ,x ,y))) (defrewrite logandc1 (x y) `(logand (lognot ,x) ,y)) (defrewrite logandc2 (x y) `(logand ,x (lognot ,y))) (defrewrite logorc1 (x y) `(logior (lognot ,x) ,y)) (defrewrite logorc2 (x y) `(logior ,x (lognot ,y))) (defmacro def-n-arg-compare (name rest 2-arg) `(defrewrite ,name (&rest ,rest) `(and ,@(maplist #'(lambda (l) (if (null (cdr l)) 't `(,',2-arg ,(car l) ,(cadr l)))) ,rest)))) ;;; NOTE: Because of Common LISP brain dammage and ambiguity the = functions ;;; might need to be full tree-wise instead of pair-wise. This is because ;;; of complications involving rationals and different sizes of floats. (def-n-arg-compare = numbers 2-arg-=) (def-n-arg-compare < numbers 2-arg-<) (def-n-arg-compare > numbers 2-arg->) (def-n-arg-compare <= numbers 2-arg-<=) (def-n-arg-compare >= numbers 2-arg->=) ;;; /= is "all different" (defrewrite /= (&rest numbers) `(AND ,@(mapcon #'(lambda (args) (if (null (cdr args)) (list 'T) (let ((arg (car args))) (mapcar #'(lambda (next-arg) `(NOT (= ,arg ,next-arg))) (cdr args))))) numbers))) ; currently constant byte specs are lambda byte specs ; computed byte specs are K byte specs ;(defrewrite byte (width position) ; `(hw:dpb ,width vinc:%%byte-size ,position)) ;;; $$$ This byte-size rewriter was not being used (since (not (eq 'nc:byte-size 'li:byte-size))) ;;; If it was being used I believe it is incorrect. <21-Nov-88 wkf> #+Removed (defrewrite byte-size (byte-spec) (setq byte-spec (nlisp:macroexpand byte-spec)) (if (constantp byte-spec) (byte-size (eval byte-spec)) `(hw:ldb ,byte-spec system:%%byte-specifier-position #|vinc:%%byte-position|# ,byte-spec))) ;once only ;;; #'(lambda ... would be taken care of by simplify-funcall anyway (defrewrite funcall (fn &rest args) (if (and (consp fn) (eq (car fn) 'FUNCTION)) `(,(cadr fn) . ,args) `(nc:funcall-internal ,fn . ,args))) ; $$$ Funcall-internal, a primop. <21-Nov-88 wkf> (defrewrite li:apply (function arg &rest more-args) `(nc:apply-internal ,function ,arg . ,more-args)) ; $$$ Apply-internal, a primop. <21-Nov-88 wkf> ;(ndefmacro mapcar (fn &rest lists) ; (let ((map-name (gensym 'map)) ; (call-fn (cond ((listp fn) ; (cond ((eq (car fn) 'lambda) (list fn)) ;???? ; ((eq (car fn) 'function) (list (cadr fn))) ; (t (list 'funcall fn)))) ; (t (list 'funcall fn)))) ; (vars '())) ; (do ((l lists (cdr lists))) ; ((null l)) ; (push (gensym 'v) vars)) ; ;; Cons up result ; (let ((map-result (gensym 'res)) ; (map-temp (gensym 'temp)) ; (map-val (gensym 'val))) ; `(let ((,map-result) ; (,map-temp)) ; (labels ((,map-name ,vars ; (if (not (or ,@(mapcar #'(lambda (var) `(null ,var)) ;atom? ; vars))) ; (progn ; (let ((,map-val (ncons (,@call-fn . ,(mapcar #'(lambda (var) ; `(car ,var)) ; vars))))) ; (if ,map-temp ; (rplacd ,map-temp ,map-val) ; (setq ,map-result ,map-val)) ; (setq ,map-temp ,map-val)) ; (,map-name ,@(mapcar #'(lambda (var) `(cdr ,var)) vars)))))) ; (,map-name . ,lists)) ; ,map-result)))) ;;; $$$ Fixed K references (CAR and CDR ) <21-Nov-88 wkf> (defrewrite li:mapc (fn &rest lists) (let ((vars (mapcar #'(lambda (l) (declare (ignore l)) (gensym 'v)) lists))) `(DO ,(mapcar #'(lambda (var list) `(,var ,list (li:CDR ,var))) vars lists) ((OR ,@(mapcar #'(lambda (var) `(NULL ,var)) vars))) (FUNCALL ,fn ,@(mapcar #'(lambda (var) `(li:CAR ,var)) vars))))) (defrewrite li:mapcar (fn &rest lists) (let ((vars (mapcar #'(lambda (l) (declare (ignore l)) (gensym 'v)) lists)) (map-result (gensym 'res)) (map-temp (gensym 'temp)) (map-val (gensym 'val))) `(DO (,@(mapcar #'(lambda (var list) `(,var ,list (LI:CDR ,var))) vars lists) ,map-result ,map-temp) ((OR ,@(mapcar #'(lambda (var) `(NULL ,var)) vars)) ,map-result) (LET ((,map-val (LI:CONS (FUNCALL ,fn ,@(mapcar #'(lambda (var) `(LI:CAR ,var)) vars)) NIL))) (IF ,map-temp (LI:RPLACD ,map-temp ,map-val) (SETQ ,map-result ,map-val)) (SETQ ,map-temp ,map-val))))) (defrewrite li:list (&rest elements) (case (length elements) (0 'nil) ;; @@@ Could be done as an ncons <21-Nov-88 wkf> (1 (cons 'li:cons `(,(car elements) nil))) (2 (cons 'li:list2 elements)) (3 (cons 'li:list3 elements)) (4 (cons 'li:list4 elements)) (t (cons 'li:listn elements)))) (defrewrite li:char (string index) `(li:svref ,string ,index)) (setf:defsetf li:char array:svset) (defrewrite li:typep (&whole form) (li:rewrite-typep form)) ;;+++ When this doesn't resolve to anything need to call nlisp:typep. --wkf (def-n-arg-compare li:char< characters li:%char< ) (def-n-arg-compare li:char<= characters li:%char<=) (def-n-arg-compare li:char= characters li:%char= ) (def-n-arg-compare li:char>= characters li:%char>=) (def-n-arg-compare li:char> characters li:%char> ) (defrewrite li:CHAR/= (&rest characters) `(AND ,@(mapcon #'(lambda (args) (if (null (cdr args)) (list 'T) (let ((arg (car args))) (mapcar #'(lambda (next-arg) `(li:%char= ,arg ,next-arg)) (cdr args))))) characters))) ;;; CHAR-EQUAL and its brothers are too hairy to open-code. What we do here is just try ;;; to avoid the expense of &REST arguments for the common cases of these functions. (defmacro define-char-????-predicate (name 2-arg-function 3-arg-function) `(defrewrite ,name (arg1 &optional (arg2 nil arg2-p) (arg3 nil arg3-p) &rest args) (cond (args ; are there more than three args? `(,',name ,arg1 ,arg2 ,arg3 ,@args)) (arg3-p ; three args? `(,',3-arg-function ,arg1 ,arg2 ,arg3)) (arg2-p ; two args? `(,',2-arg-function ,arg1 ,arg2)) (t 't)))) ; one arg? (define-char-????-predicate li:char-equal li:char-equal-2-args li:char-equal-3-args) (define-char-????-predicate li:char-not-equal li:char-not-equal-2-args li:char-not-equal-3-args) (define-char-????-predicate li:char-lessp li:char-lessp-2-args li:char-lessp-3-args) (define-char-????-predicate li:char-greaterp li:char-greaterp-2-args li:char-greaterp-3-args) (define-char-????-predicate li:char-not-lessp li:char-not-lessp-2-args li:char-not-lessp-3-args) (define-char-????-predicate li:char-not-greaterp li:char-not-greaterp-2-args li:char-not-greaterp-3-args) ;;; VINC:TYPE-TEST through LI:DOUBLE-FLOAT-P used to be in "K; TYPE-PREDICATES" (ndefmacro vinc:type-test (object type) `(HW:FIELD= ,object (HW:DPB-UNBOXED ,type vinc:%%data-type 0) VINC:%%DATA-TYPE)) (defrewrite prims:null (x) `(if ,x nil t)) (defrewrite vinc:consp (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-CONS)) (defrewrite vinc:atom (object) `(NOT (vinc:CONSP ,object))) (defrewrite vinc:complexp (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-COMPLEX)) (defrewrite vinc:characterp (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-CHARACTER)) (defrewrite vinc:arrayp (object) `(HW:FIELD= GR:*RANDOM-ARRAY* ,object VINC:%%DATA-TYPE)) (defrewrite vinc:compiled-function-p (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-COMPILED-FUNCTION)) (defrewrite vinc:make-fixnum (object) "Puts fixnum type code into object and set Zero and Negative status bits accordingly." `(hw:merge-24 gr:*zero* ,object) ;;||| Chaned 10/13/88 --wkf #+Does-not-set-status-bits-for-negative`(HW:DPB-BOXED VINC:$$DTP-FIXNUM VINC::%%DATA-TYPE ,object) ) #+Not-currently-used (defrewrite vinc:make-short-float (object) "Puts short type code on top of object word" `(HW:DPB-BOXED VINC:$$DTP-SHORT-FLOAT VINC::%%DATA-TYPE ,object)) ;;||| Added 10/13/88 --wkf ;;; These are not Common Lisp but we find them useful ;;; TYPEP expands into them (defrewrite vinc:fixnump (object) `(HW:FIELD= GR:*ZERO* ,object VINC:%%DATA-TYPE)) (defrewrite vinc:bignump (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-BIGNUM)) (defrewrite vinc:short-float-p (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-SHORT-FLOAT)) (defrewrite vinc:single-float-p (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-SINGLE-FLOAT)) (defrewrite vinc:long-float-p (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-DOUBLE-FLOAT)) (defrewrite vinc:double-float-p (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-DOUBLE-FLOAT)) (defrewrite vinc:structure-p (object) `(HW:FIELD= GR:*RANDOM-STRUCTURE* ,object VINC:%%DATA-TYPE)) (defrewrite vinc:instance-p (object) `(VINC:TYPE-TEST ,object VINC:$$DTP-INSTANCE)) (defrewrite li:make-string (&whole form length &key (initial-element nil init-p)) (if (> (length form) 2) (if init-p `(li:make-string-with-init ,length ,initial-element) form) `(array::make-string-no-init ,length))) ;;; $$$Added defrewrites that were sprinkled through the system. <18-Nov-88 JIM> ;;; $$$ arithmetic.lisp <18-Nov-88 JIM> li:: (defrewrite max (&whole form) (let ((length-form (length form))) (cond ((= length-form 2) (second form)) ((= length-form 3) `(MAX-2 . ,(cdr form))) (t form))) ) li:: (defrewrite min (&whole form) (let ((length-form (length form))) (cond ((= length-form 2) (second form)) ((= length-form 3) `(MIN-2 . ,(cdr form))) (t form)))) ;;@@@ Is it worth saving consing with a min/max-3+ ??? --wkf ;;; $$$ array2.lisp <18-Nov-88 JIM> array:: (defrewrite aref (&whole form array &rest subscripts) (lisp:case (lisp:length subscripts) (1 `(AREF-1 ,array . ,subscripts)) (2 `(AREF-2 ,array . ,subscripts)) (t form))) array:: (defrewrite aset (&whole form value array &rest subscripts) (lisp:case (lisp:length subscripts) (1 `(ASET-1 ,value ,array . ,subscripts)) (2 `(ASET-2 ,value ,array . ,subscripts)) (t form))) array:: (defrewrite make-array (&whole form dimensions &rest options &key (element-type t element-type-p)) (cond ((null options) (cond ((numberp dimensions) `(MAKE-VECTOR ,dimensions)) (t `(MAKE-EASY-ARRAY ,dimensions)))) ((and element-type-p (null (lisp:cddr options))) (let ((type ;; do something clever with constantp here (or (eq element-type t) (and (lisp:consp element-type) (eq (lisp:car element-type) 'QUOTE) (lisp:cadr element-type))))) (if type (let ((array-type (array-type-from-element-type type))) (if (numberp dimensions) (cond ((= array-type art-q) `(MAKE-VECTOR ,dimensions)) ((= array-type art-string) `(MAKE-STRING ,dimensions)) (t `(MAKE-1D-ARRAY ,dimensions ,array-type))) `(MAKE-EASY-ARRAY ,dimensions ,array-type))) `(MAKE-EASY-ARRAY-WITH-ELEMENT-TYPE ,dimensions ,element-type)))) (t form)))