;;; -*- Mode: Lisp; Package: Prolog; Base: 10. ; -*- ;;; (C) Copyright 1983,1984,1985, Uppsala University ;;this file contains a few macros that need to be shared between ;;instead-of-ucode and support in LM-Prolog ;;Some of these have to be reachable from the ucode. (defvar *vector* nil "The interpreter's non-recursive environment.") (defvar *trail-array* nil "The current Prolog's reset list.") (defvar *trail* nil "Direct access variable to active count of current *TRAIL-ARRAY*") (defvar *prolog-work-area* nil "The current area for temporary consing in Prolog") (defvar *universe* () "Definitions of predicates are found by searching this list of worlds") (defvar *conses-alist* () "Alist used when copying interpreter terms to preserve isomorphy and guarantee termination" ) (defvar *unsafe-rest-argument* #-3600 nil #+3600 t "T if predicator being defined should copy its rest argument.") #-3600 (defsubst trail (x) (or (array-push *trail-array* x) (array-push-extend *trail-array* x))) #+3600 (defun trail (x) (let ((index *trail*) (len (array-leader *trail-array* 1))) (cond ((>= index len) (adjust-array-size *trail-array* (setf (array-leader *trail-array* 1) (+ len (// len 2)))))) (aset x *trail-array* index) (incf *trail*) index)) (defsubst untrail (mark) (%untrail mark)) (defsubst value-cell-name (value-cell) (rest1 (%make-pointer dtp-list value-cell))) (defsubst fast-locative-p (x) (eq (%data-type x) dtp-locative)) (defsubst value-cell-p (x) (fast-locative-p x)) (deffsubst rest-arg-fixup-loop (rest-arg) (cond ((= dtp-locative (%p-data-type rest-arg)) (%p-store-data-type rest-arg dtp-external-value-cell-pointer))) (SELECT (%P-CDR-CODE REST-ARG) (CDR-NEXT (rest-arg-fixup-loop (rest1 rest-arg))) (CDR-NORMAL (rest-arg-fixup-loop (%MAKE-POINTER-OFFSET DTP-LIST REST-ARG 1))))) (defun rest-arg-copy (rest-arg) (setq rest-arg (copylist rest-arg *prolog-work-area*)) (cond ((consp rest-arg) (rest-arg-fixup-loop rest-arg))) rest-arg) (defun rest-arg-fixup (rest-arg) (cond ((consp rest-arg) (rest-arg-fixup-loop rest-arg))) rest-arg) #+lexical (defmacro invoke (x) (cond ((and (consp x) (eq 'continuation (car x))) (cadr x)) (t `(funcall ,x)))) #-lexical (defmacro invoke (x) (cond ((atom x) `(%invoke ,x)) ((eq 'continuation (car x)) (second x)) ((eq 'quote (car x)) `(apply ',(car (second x)) ',(cdr (second x)))) (t `(%invoke ,x)))) ;;the following three macros make life easier for the system's consing. #-(OR 3600 PROLOG-MICRO-CODE) (progn 'compile (defmacro prolog-cons (x y) `(REST-ARG-FIXUP (cons-in-area ,X ,Y *prolog-work-area*))) (defmacro prolog-list (&rest elements) (COND (ELEMENTS `(REST-ARG-FIXUP (list-in-area *prolog-work-area* ,@ELEMENTS))))) (defmacro prolog-list* (&rest elements) (COND ((CDR ELEMENTS) `(REST-ARG-FIXUP (list*-in-area *prolog-work-area* ,@ELEMENTS))) (ELEMENTS (CAR ELEMENTS)) (T (BREAK "PROLOG-LIST* of 0 arguments.")))) ) #+PROLOG-MICRO-CODE (progn 'compile (defmacro prolog-cons (x y) `(cons-in-area ,(reference-if-needed x) ,(reference-if-needed y) *prolog-work-area*)) (defmacro prolog-list (&rest elements) `(list-in-area *prolog-work-area* ,@(mapcar #'reference-if-needed elements))) (defmacro prolog-list* (&rest elements) `(list*-in-area *prolog-work-area* ,@(mapcar #'reference-if-needed elements))) (deffun reference-if-needed (form) ;7.12 (cond ((consp form) (selectq (car form) (let ;common in nested continuations (selectq (car (reference-if-needed (third form))) (%reference `(%reference ,form)) (t form))) ((%dereference %reference) (reference-if-needed (cadr form))) ((quote function prolog-cons prolog-list prolog-list* continuation current-entrypoint) form) (t `(%reference ,form)))) ((and (symbolp form) (not (memq form '(nil t .continuation.)))) `(%reference ,form)) (t form)))) (comment #+3600 (progn 'compile (defmacro prolog-cons (x y) `(cons-in-area ,(reference-if-needed x) ,(reference-if-needed y) *prolog-work-area*)) (defmacro prolog-list (&rest elements) `(prolog-list* ,@elements nil)) (defmacro prolog-list* (&rest elements) (turn-into-prolog-cons elements)) (defun turn-into-prolog-cons (elements) (cond ((cdr elements) `(prolog-cons ,(car elements) ,(turn-into-prolog-cons (cdr elements)))) (t (car elements)))))) #+3600 (progn 'compile (defmacro prolog-list (&rest elements) (let ((l (length elements))) (cond ((zerop l) `nil) (t `(%prolog-list ,l ,@elements))))) (defmacro prolog-list* (&rest elements) (let ((l (length elements))) (cond ((= 1 l) `,(car elements)) (t `(%prolog-list* ,l ,@elements)))))) (defvar dtp-kludge (cond ((boundp 'si:dtp-rplacd-forward) si:dtp-rplacd-forward) (t dtp-header-forward))) #-3600 (defmacro with-cons-bound-to-cons (x y &body body) `(without-interrupts (bind (%make-pointer dtp-locative ,x) (%make-pointer dtp-kludge ,y)) ,@body)) #+3600 (defmacro with-cons-bound-to-cons (x y &body body) `(with-stack-list* (with-cons-bound-to-cons-item ,x ,y) (with-stack-list* (*conses-alist* with-cons-bound-to-cons-item *conses-alist*) ,@body))) #-3600 (defmacro with-cons-parts (ignore &body body) `(progn . ,body)) #+3600 (defmacro with-cons-parts (x &body body) `(let ((with-cons-parts-item (assq ,x *conses-alist*))) (let-if with-cons-parts-item ((,x (cdr with-cons-parts-item))) ,@body))) ;;;Here is the beginning of a simple scheme for dispatching on things like ;;;the data-type. (deffun variables-used (varlist form) (cond (varlist (cond ((not (contains form (car varlist))) (variables-used (cdr varlist) form)) (t (cons (car varlist) (variables-used (cdr varlist) form))))))) (defmacro define-dispatch-table (macro-name ARGLIST NEW-ARGLIST OFFSET-FORMS &rest make-array-arguments) " (DEFINE-DISPATCH-TABLE ...) followed by (DEFINE-DISPATCH-ENTRY ...) will set up a dispatch table such that ( ) applies (AREF . ) to ." (let* ((table-name (intern (string-append macro-name "-DISPATCH-TABLE") ':prolog)) (unsafe (intersection (variables-used arglist offset-forms) (variables-used arglist new-arglist))) (safe (mapcar #'(lambda (x) (intern (format nil "~a-defsubst" x) ':prolog)) unsafe)) (sublis-alist (mapcar #'cons unsafe safe))) `(progn 'compile (defvar ,table-name (make-array . ,make-array-arguments)) (defsubst ,macro-name ,arglist (let ,(mapcar #'list safe unsafe) (funcall (aref ,table-name ,@(sublis sublis-alist offset-forms)) ,@(sublis sublis-alist new-arglist))))))) (defmacro define-dispatch-entry (macro-name dispatch-name arglist &body body) (let ((entry-name (intern (FORMAT NIL "~A-~A" macro-name dispatch-name) ':prolog))) `(progn 'compile (defun ,entry-name ,arglist . ,body) (aset #',entry-name ,(intern (string-append macro-name "-DISPATCH-TABLE") ':prolog) ,dispatch-name)))) (defmacro alter-dispatch-entry (macro-name dispatch-name spec) `(aset ,spec ,(intern (string-append macro-name "-DISPATCH-TABLE") ':prolog) ,dispatch-name)) ;;A common special case in LM-Prolog is: dispatch on data-type of 1st arg ;; and default with the fastest identity function. (defmacro define-dtp-table (name arglist &rest options) `(define-dispatch-table ,name ,arglist ,arglist ((%data-type ,(first arglist))) #-3600 32. #+3600 64. ,@options)) (defmacro define-dtp-entry (x y z &body body) `(define-dispatch-entry ,x ,y ,z ,@body)) (defmacro alter-dtp-entry (&rest arglist) `(alter-dispatch-entry ,@arglist)) ;Has to be around when UCODE is fasloaded... #-3600 #8R COMPILER: (DEFMACRO PROLOG:DEFMIC (&REST ARGS) (LET ((FN (CAR ARGS))) `(EVAL-WHEN (#+cadr COMPILE EVAL LOAD) (DEFMIC ,@ARGS) ,@(COND ((MEMQ '&REST (THIRD ARGS)) `((DEFPROP ,FN ,(DPB (- (LENGTH (THIRD ARGS)) (LENGTH (MEMQ '&REST (THIRD ARGS)))) 0606 77) ARGS-INFO))) (T `((DEFPROP ,FN ,(DPB (LENGTH (THIRD ARGS)) 0606 (LENGTH (THIRD ARGS))) ARGS-INFO)))) #-cadr (LET ((SYMBOL-INDEX (- (GET ',FN 'QLVAL) 200)) (SI:%INHIBIT-READ-ONLY T)) (SETF (SYS:MICRO-CODE-SYMBOL-NAME-AREA SYMBOL-INDEX) ',FN)))))