;;; -*- Mode: Lisp; Package: Prolog; Base: 10. ; Options:((WORLD CPROLOG) (DETERMINISTIC ALWAYS)); -*- ;;; (C) Copyright 1983,1984,1985, Uppsala University ;;this is the Concurrent Prolog interpreter written in LM-Prolog ;;written 11/14/83 by E. Shapiro and Ken Kahn ;;Compiler written and graphics rewritten on 17 dec 1984 by Mats Carlsson. ;;; Read Only Variables. (defmethod (read-only-variable :unify) (other) (let ((value (%dereference cell))) (cond ((not (value-cell-p value)) (unify value other))))) (defmethod (read-only-variable :ordinary-term) () (let ((value (%dereference cell))) (cond ((value-cell-p value) (values self t)) (t value)))) (defmethod (read-only-variable :lisp-form) (mode) (let ((value (%dereference cell))) (cond ((value-cell-p value) (selectq mode (:copy (prolog-intern "~A~A" (extended-name value) *variable-prefix*)) (t self))) (t value)))) (defmethod (read-only-variable :variable-p) () (value-cell-p (%dereference cell))) (DEFMETHOD (READ-ONLY-VARIABLE :PRINT-SELF) (STREAM &REST IGNORE) (let ((value (%dereference cell))) (cond ((value-cell-p value) (FORMAT STREAM "~A~A" (value-cell-name value) *variable-prefix*)) (t (FUNCALL (OR PRIN1 #'PRIN1) value STREAM))))) (make-instance 'read-only-variable) ;;initializes things... ;;; Runtime. (declare (special puser:tvrtle-window)) (define-predicate cptop ((cptop . ?goals) (cp . ?goals))) (define-predicate cptop (:options (:world :graphics)) ((cptop . ?goals) (lisp-command (send puser:tvrtle-window ':clear-screen) :dont-invoke) (cp-bagel . ?goals))) (define-predicate cp ((cp . ?goals) (append ?sys0 ?goals (:cycle . ?sys)) (cpsolve ?sys0 ?sys :nodeadlock))) (define-predicate cpreduce (:options (:world :cp-bf)) ((cpreduce ((?p . ?args) . ?front0) ?back0 ?front0 ?back1) (?p ?args ?back0 ?back1))) (define-predicate cpreduce (:options (:world :cp-df)) ((cpreduce ((?p . ?args) . ?front1) ?back0 ?front0 ?back0) (?p ?args ?front0 ?front1))) (define-predicate cpstate ((cpstate :cycle :nodeadlock :deadlock)) ((cpstate (? . ?) ?old ?old))) (define-predicate cpsolve (:options (:argument-list (+ * +))) (;Reduction... (cpsolve ?front0 ?back0 ?) (cpreduce ?front0 ?back0 ?front1 ?back1) (cut) (cpsolve ?front1 ?back1 :nodeadlock)) (;Empty system... (cpsolve (:cycle) () ?) (cut)) (;Suspension... (cpsolve (?goal . ?front) (?goal . ?back) ?old) (cpstate ?goal ?old ?new) (cut) (cpsolve ?front ?back ?new))) (define-predicate :prolog ((:prolog ?args ?s ?s) (and . ?args))) (define-predicate :at ((:at ((?p . ?args) . ?) ?s0 ?s) (?p ?args ?s0 ?s))) ;;; Graphics. (define-predicate bagel-stream :(options (world graphics)) ((bagel-stream ?pos0) (lisp-value ?instance (make-instance-in-area *prolog-work-area* 'demo-graphics) :dont-invoke) (constrain ?pos0 (graphics-demos-stream-server ?instance ?pos0)))) (define-predicate bagel-stream ((bagel-stream . ?))) (defvar *bagel-pixels-x* 152) (defvar *bagel-pixels-y* 32) (defmethod (demo-graphics :bagel) (goal turtle) (unwind-protect (let* ((turtle-x (car turtle)) (turtle-y (cadr turtle)) (turtle-dx (caddr turtle)) (turtle-dy (cadddr turtle)) (arrow (select (+ turtle-dx turtle-dy turtle-dy) (1 #\right-arrow) (-1 #\left-arrow) (-2 #\uparrow) (2 #+symbolics #\downarrow #-symbolics #\down-arrow))) (window puser:tvrtle-window) (msg (prolog-string "~16s" goal))) (multiple-value-bind (xpos ypos) (compute-bagel-pos turtle-x turtle-y) (send window ':set-current-font 1) (send window ':set-cursorpos xpos ypos) (send window ':draw-rectangle *bagel-pixels-x* *bagel-pixels-y* xpos ypos tv:alu-andca) (send window ':tyo arrow) (send window ':string-out msg 0 16) (send window ':tyo arrow)) (send window ':set-current-font 0)))) (defun compute-bagel-pos (bagel-x bagel-y) (multiple-value-bind (size-x size-y) (send puser:tvrtle-window ':inside-size) (let* ((xlen (// size-x *bagel-pixels-x*)) (ylen (// size-y *bagel-pixels-y*)) (virtual-processor (+ bagel-x (// xlen 2) (* xlen (+ bagel-y (// ylen 2))))) (bagel-processor (\ virtual-processor (1- (* xlen ylen))))) (cond ((< bagel-processor 0) (incf bagel-processor (1- (* xlen ylen))))) (values (+ 2 (* *bagel-pixels-x* (\ bagel-processor xlen))) (+ 2 (* *bagel-pixels-y* (// bagel-processor xlen))))))) (define-predicate cp-bagel ((cp-bagel . ?goals0) (cpreduce-system ?goals0 (0 0 0 +1) ?sys0 (:cycle . ?sys)) (bagel-stream ?graph0) (cpsolve-bagel ?sys0 ?sys :nodeadlock ?graph0))) (define-predicate cpsolve-bagel ((cpsolve-bagel ((:process . ?args) . ?front0) ?back0 ? ?graph0) (cpreduce-bagel ?graph0 ?graph ?front0 ?back0 ?front1 ?back1 . ?args) (cut) (cpsolve-bagel ?front1 ?back1 :nodeadlock ?graph)) ((cpsolve-bagel (:cycle) () ? ()) (cut)) ((cpsolve-bagel (?goal . ?sys0) (?goal . ?sys) ?old ?graph) (cpstate ?goal ?old ?new) (cut) (cpsolve-bagel ?sys0 ?sys ?new ?graph))) (define-predicate cpreduce-bagel (:options (:world :cp-bf)) ((cpreduce-bagel ?graph0 ?graph ?front0 ?back0 ?front0 ?back1 (?p . ?args) ?turtle) (= ?graph0 ((:bagel (?p . ?args) ?turtle) . ?graph)) (?p ?args ?temp ()) (cpreduce-system ?temp ?turtle ?back0 ?back1))) (define-predicate cpreduce-bagel (:options (:world :cp-df)) ((cpreduce-bagel ?graph0 ?graph ?front1 ?back0 ?front0 ?back0 (?p . ?args) ?turtle) (= ?graph0 ((:bagel (?p . ?args) ?turtle) . ?graph)) (?p ?args ?temp ()) (cpreduce-system ?temp ?turtle ?front0 ?front1))) (define-predicate cpreduce-system ((cpreduce-system () ? ?sys ?sys)) ((cpreduce-system (?goal . ?goals) ?turtle (?p-goal . ?sys0) ?sys) (cpreduce-system-1 ?goal ?turtle ?p-goal) (cpreduce-system ?goals ?turtle ?sys0 ?sys))) (define-predicate cpreduce-system-1 ((cpreduce-system-1 (:at ?goal . ?d-turtle) ?turtle (:process ?goal ?n-turtle)) (cut) (move-turtle ?turtle ?d-turtle ?n-turtle)) ((cpreduce-system-1 ?goal ?turtle (:process ?goal ?turtle)))) (define-predicate move-turtle ((move-turtle ?t () ?t)) ((move-turtle (?x ?y ?dx ?dy) (:forward . ?t0) ?t) (sum ?x1 ?x ?dx) (sum ?y1 ?y ?dy) (move-turtle (?x1 ?y1 ?dx ?dy) ?t0 ?t)) ((move-turtle (?x ?y ?dx ?dy) ((:forward ?amt) . ?t0) ?t) (lisp-value ?x1 (TRUNCATE (+ '?x (* '?dx ?amt))) :dont-invoke) (lisp-value ?y1 (TRUNCATE (+ '?y (* '?dy ?amt))) :dont-invoke) (move-turtle (?x1 ?y1 ?dx ?dy) ?t0 ?t)) ((move-turtle (?x ?y ?dx ?dy) (:back . ?t0) ?t) (difference ?x1 ?x ?dx) (difference ?y1 ?y ?dy) (move-turtle (?x1 ?y1 ?dx ?dy) ?t0 ?t)) ((move-turtle (?x ?y ?dx ?dy) (:right . ?t0) ?t) (turn ?dx ?dy ?dx1 ?dy1) (move-turtle (?x ?y ?dx1 ?dy1) ?t0 ?t)) ((move-turtle (?x ?y ?dx ?dy) (:left . ?t0) ?t) (turn ?dx1 ?dy1 ?dx ?dy) (move-turtle (?x ?y ?dx1 ?dy1) ?t0 ?t))) (define-predicate turn ((turn 0 1 -1 0)) ((turn -1 0 0 -1)) ((turn 0 -1 1 0)) ((turn 1 0 0 1))) ;;; Compiler. DEFINE-CP transforms into a predicate of exactly three arguments: ;;; the "real" arglist, head of body goal list, tail of body goal list. ;;; Currently, the goal list will be created before the guard is run. ;;; It could put after the guard but then PROVE-CONJUNCION would be called much ;;; more often. (define-predicate define-cp (:options (:lisp-macro-name define-cp)) ((define-cp ?name . ?rules) (map define-cp-rule ?rules ?cp-rules) (define-predicate ?name . ?cp-rules))) (define-predicate define-cp-rule ((define-cp-rule (:options . ?options) (:options . ?options))) ((define-cp-rule ((?p . ?args) . ?guard-body) ((?p ?args ?sys0 ?sys) . ?cp-guard)) (guard-and-body ?guard-body ?guard ?body) (optimize-guard ?guard ?cp-guard) (append ?sys0 ?body ?sys))) (define-predicate optimize-guard ((optimize-guard () ())) ((optimize-guard ((:prolog . ?goals)) ?goals)) ((optimize-guard ?processes ((cp . ?processes))))) (define-predicate guard-and-body ((guard-and-body ?all ?guard ?body) (append ?all ?guard ((cut)) ?body)) ((guard-and-body ?body () ?body))) ;;; Utilities. (define-predicate :top-level-predication :(options (world concurrent-prolog-top-level)) ((:top-level-predication ?predication) (cases ((atomic ?predication) (error ':bad-predication "~s must be a predication (i.e. a list)" ?predication)) ((variables ?variables ?predication) (variable-names ?variable-names ?predication) (cases ((cptop ?predication) (format t "~&OK") (print-bindings ?variable-names ?variables)) ((format t "~&No answer") (cut) (false))))))) (GLOBALIZE 'DEFINE-CP ':PGLOBAL) (GLOBALIZE 'CPTOP ':PGLOBAL) (ADD-WORLD :CP-BF)