LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 2 :LENGTH-IN-BYTES 1362 :AUTHOR "SAM" :CREATION-DATE 2723137372 :QFASLP NIL :LENGTH 1362 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "CIRCULATION-DIRECTORY-LISTING" :TYPE "TEXT" :VERSION 8) ŤŤŤ‰‰‰ LISP II COURSE MATERIALŤ‰‰‰ -----------------------ŤŤ DUKE: LISP2-CIRCULATION; *.*#*ŤŤ AI-PROGRAMMING-EXERCISES.TEXTŤ CIRCULATION-DIRECTORY-LISTING.TEXTŤ DEBUGGING-EXERCISES-PAGE-1.TEXTŤ DEFMACRO-EXERCISE-ANSWERS.LISPŤ DEFMACRO-EXERCISES.LISPŤ DEFMACRO-REQUIRED-EXERCISE.LISPŤ EMPTY.CHARTŤ FANCIER-LISPM.LISPŤ FORTRAN-CALL.LISPŤ LINE-EDITOR.LISPŤ LISPM.INITŤ LISPM.LISPŤ ORG.LISPŤ PAINT.LISPŤ PROCESS-BRINGUP-WINDOW.LISPŤ Prolog system as loaded by PROLOG-INIT.LISPŤ QUERIES.LISPŤ QUICK-STATS.LISPŤ RAPID-PROTOTYPING.LISPŤ RAPID-PROTOTYPING.LISPŤ RECURSIVE-DESCENT.LISPŤ RECURSIVE-DESCENT-EX1.LISPŤ RECURSIVE-DESCENT-EX2.LISPŤ SPACE-FLAVOR.LISPŤ TEACH-ZMACS.TEXTŤ TURTLE.LISPŤ TURTLE-CONSTRAINT-FRAME-KEY-TOGGLE.TEXTŤ TURTLE-CONSTRAINT-FRAME-TWO-CONFIG.TEXTŤ TURTLE-CONSTRAINT-ONE-CONFIG.LISPŤ TURTLE-CONSTRAINT-ONE-CONFIG-EXERCISE.LISPŤ TURTLE-CONSTRAINT-TWO-CONFIG.LISPŤ TURTLE-HACKS.LISPŤ TURTLE-POND.LISPŤ TURTLE-PROCESS.LISPŤ WINDOW-BRINGUP-PROCESS.LISPŤŤ PLEASE NOTE: This education material is not specifically supported by LMI.Ť‰Please call Lorin Wilde of the Education Division at (617) 682 - 0500Ť‰if you have any questions or comments concerning these programs.ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 9 :LENGTH-IN-BYTES 9142 :AUTHOR "SAM" :CREATION-DATE 2722219762 :QFASLP NIL :LENGTH 9142 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "CL-INIT" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#+lispm (send *standard-output* :clear-screen)Ť#-lispm (princ #\page)Ť(format t "ŤŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤŤ___________________________________________________________________________ŤSamuel F. Pilato~2%")ŤŤŤŤ;;;;CL-INITŤ;;;Ť;;; CommonLisp InitializationŤŤ(provide 'cl-init)ŤŤŤŤ;;;;Message at Start of LoadingŤŤ(format t "Ť Initializing a CommonLisp environment: providing for ...ŤŤ CommonLisp Readtable InitializationŤ Maintaining a Module RegistryŤ Enhancement of REQUIRE Function (REQUIRE being redefined)Ť Ordered Compiling and Loading of Modules~%")ŤŤŤŤ;;;;CommonLisp Readtable InitializationŤŤ#+lispmŤ(defmacro cl-init ()Ť "Set *readtable* to a copy of the standard CommonLisp readtable.Ť This is undone upon logout."Ť `(progn (login-forms (setq *readtable* (copy-readtable nil))) (values)))ŤŤ#-lispmŤ(defmacro cl-init ()Ť "Set *readtable* to a copy of the standard CommonLisp readtable."Ť `(progn (setq *readtable* (copy-readtable nil)) (values)))ŤŚŤ;;;;Module RegistryŤŤ(defvar *module-pathname-defaults* *default-pathname-defaults*Ť "defaults for completing a pathname to a module's file")ŤŤ(defvar *module-registry* nilŤ "registry of modules and where to find their associated files:Ť The registry is an alist where each key is a module name (as a string)Ť and its associated datum is a list of pathnames to the module's files.Ť Keys should be tested with STRING= .")ŤŤ(defun module-pathnames (module-name &aux pair)Ť "Given the name of a module, return a list of pathnames to the module'sŤ files. MODULE-NAME may be a module name (as a string) or a symbol whoseŤ print name is the module name. If a module is not registered inŤ *MODULE-REGISTRY*, the module name merged withŤ *MODULE-PATHNAME-DEFAULTS* is listed as the sole pathname."Ť (if (setq pair (assoc module-name *module-registry* :test #'string=))Ť (cdr pair)Ť (list (merge-pathnames module-name *module-pathname-defaults*))))ŤŤ(defmacro with-module-pathname-defaults ((pathname-defaults) &body body)Ť "With *MODULE-PATHNAME-DEFAULTS* bound to PATHNAME-DEFAULTS, evaluate theŤ BODY."Ť `(let ((*module-pathname-defaults* ,pathname-defaults)) ,@body))ŤŤ(defun register-moduleŤ (module-nameŤ‰&optional (pathname (string module-name))Ť‰&aux (module-name-string (string module-name))Ť‰ (pathnames (if (listp pathname) pathname (ncons pathname))))Ť "Register a module so that when it is REQUIREd and its associated filesŤ are neither already loaded nor named in the REQUIRE call, the system canŤ determine which files to load.Ť MODULE-NAME may be a module name (as a string) or a symbol whose printŤ name is the module name. PATHNAME, if present, may be a single non-NILŤ pathname or a list of pathnames whose files are to be loaded in order,Ť left to right. If PATHNAME is not provided, the module name is takenŤ also to be the sole pathname to its files. All pathnames are defaultedŤ from *MODULE-PATHNAME-DEFAULTS* . The module name is returned."Ť (setq pathnames (mapcar #'(lambda (p) (merge-pathnamesŤ‰‰‰‰‰ p *module-pathname-defaults*))Ť‰‰‰ pathnames))Ť (push (cons module-name-string pathnames) *module-registry*)Ť module-name-string)ŤŤ(defun register-modules (&rest module-specs)Ť "See function REGISTER-MODULE . A MODULE-SPEC is either a module-nameŤ (string or symbol) or a list of a module-name followed by pathnames toŤ its associated files. A list of the module names is returned."Ť (mapcar #'(lambda (spec) (if (atom spec)Ť‰‰‰ (register-module spec)Ť‰‰‰ (register-module (car spec) (cdr spec))))Ť‰ module-specs))ŤŚŤ;;;;Extension of REQUIRE Beyond the 1986 ZetaLisp VersionŤŤ#+lispm (defparameter *my-inhibit-fdefine-warnings* t)Ť#+lispm (rotatef *my-inhibit-fdefine-warnings* inhibit-fdefine-warnings)ŤŤ(defun require (module-nameŤ‰‰&optional pathnameŤ‰‰&aux (module-name-string (string module-name)))Ť "If the named module has not been loaded as indicated by the value ofŤ *MODULES*, load the appropriate file(s).Ť MODULE-NAME may be a module name (as a string) or a symbol whose printŤ name is the module name. PATHNAME, if present, may be a single pathnameŤ or a list of pathnames whose files are to be loaded in order, left toŤ right. If PATHNAME is NIL or is not provided, we check if the module isŤ registered in *MODULE-REGISTRY*, and if that fails we take the moduleŤ name also to be the sole pathname. All unregistered pathnames areŤ defaulted from *MODULE-PATHNAME-DEFAULTS* before loading. We return aŤ list of pathnames to the files loaded."Ť (unless (member module-name-string *modules* :test #'string=)Ť (let ((pathnamesŤ‰ (if pathnameŤ‰ (mapcar #'(lambda (p)Ť‰‰‰ (merge-pathnames p *module-pathname-defaults*))Ť‰‰ (if (consp pathname) pathname (ncons pathname)))Ť‰ (module-pathnames module-name-string))))Ť (mapc #'load pathnames)Ť pathnames)))ŤŤ#+lispm (rotatef *my-inhibit-fdefine-warnings* inhibit-fdefine-warnings)ŤŚŤ;;;;Ordered Compiling and Loading of ModulesŤŤ(defconstant *lisp-type-pathname* (make-pathname :type "lisp"))ŤŤ(defun compile-load-module (module-name &rest keywords)Ť "Compile and/or load or just probe -- as optionally restricted byŤ :NO-COMPILE and/or :NO-LOAD keywords -- a module's files in order.Ť MODULE-NAME may be a module name (as a string) or a symbol whose printŤ name is the module name.Ť If successful we return a list (in compile/load order) of pathnames toŤ the module's files. (When probing, we return each file's truename ifŤ found, else NIL)."Ť (assert (null (set-difference keywords '(:no-compile :no-load)))Ť‰ (keywords) "Invalid keyword(s).")Ť (let* ((pathnames (module-pathnames module-name))Ť‰ (compile-p (not (member :no-compile keywords)))Ť‰ (load-p (not (member :no-load keywords))))Ť (if (or compile-p load-p)Ť (dolist (pathname pathnames pathnames)Ť‰(if compile-pŤ‰ (compile-file (merge-pathnames pathname *lisp-type-pathname*)))Ť‰(if load-p (load pathname)))Ť (mapcar #'probe-file pathnames))))ŤŤ(defun compile-module (module-name)Ť "Compile a module. MODULE-NAME may be a module name (as a string) or aŤ symbol whose print name is the module name. If successful we return aŤ list (in compilation order) of pathnames to the module's files."Ť (compile-load-module module-name :no-load))ŤŤ(defun load-module (module-name)Ť "Load a module. MODULE-NAME may be a module name (as a string) or aŤ symbol whose print name is the module name. If successful we return aŤ list (in order of loading) of pathnames to the module's files."Ť (compile-load-module module-name :no-compile))ŤŤ(defun probe-module (module-name)Ť "Probe a module's files. MODULE-NAME may be a module name (as a string)Ť or a symbol whose print name is the module name. We return a listŤ containing -- for each of the module's files (in compile-load order) --Ť its truename if found, else NIL."Ť (compile-load-module module-name :no-compile :no-load))ŤŚŤ(defmacro registered-modules ()Ť "Return a list of the names of registered modules, in the order in whichŤ they were first registered."Ť `(nreverse (delete-duplicates (mapcar #'car *module-registry*)Ť‰‰‰‰:test #'string=)))ŤŤ(defun compile-load-modules (&rest module-names)Ť "Compile and load modules in order. Each MODULE-NAME may be a moduleŤ name (as a string) or a symbol whose print name is the module name. IfŤ no MODULE-NAMES are provided, we use (REGISTERED-MODULES).Ť If successful we return a list (in compile/load order) of all componentŤ pathnames."Ť (apply #'append (mapcar #'compile-load-moduleŤ‰‰‰ (or module-names (registered-modules)))))ŤŤ(defun compile-modules (&rest module-names)Ť "Compile modules in order. This is similar to COMPILE-LOAD-MODULES,Ť which see."Ť (apply #'append (mapcar #'compile-moduleŤ‰‰‰ (or module-names (registered-modules)))))ŤŤ(defun load-modules (&rest module-names)Ť "Load modules in order. This is similar to COMPILE-LOAD-MODULES,Ť which see."Ť (apply #'append (mapcar #'load-moduleŤ‰‰‰ (or module-names (registered-modules)))))ŤŤ(defun probe-modules (&rest module-names)Ť "Probe modules in order. This is similar to COMPILE-LOAD-MODULES,Ť which see."Ť (apply #'append (mapcar #'probe-moduleŤ‰‰‰ (or module-names (registered-modules)))))ŤŚŤ;;;;Messages at End of LoadingŤŤ(format t "~% CommonLisp initialization is complete.~%")ŤŤ(format t "Ť To set *readtable* to a copy of the standard CommonLisp readtable, typeŤ (CL-INIT) .~%")Ť#+lispm (format t " This is undone upon logout.~%")ŤŤŤ(format t "Ť To register a module, typeŤ (REGISTER-MODULE module-name [pathname]) .ŤŤ To retrieve the names of modules currently registered, typeŤ (REGISTERED-MODULES) .ŤŤ To load a registered module -- or for that matter, often even to load aŤ simple UNregistered module -- just typeŤ (REQUIRE ) .ŤŤ Please inspect the source file for further documentation of these andŤ other new facilities.~2%")ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 1 :LENGTH-IN-BYTES 508 :AUTHOR "SAM" :CREATION-DATE 2721875314 :QFASLP NIL :LENGTH 508 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "DEFINING" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;DEFININGŤŤ(provide 'defining)ŤŤŤ(defmacro alias (inheriting-symbol inherited-symbolŤ‰‰ &body (&optional doc-string))Ť `(setf (symbol-function ',inheriting-symbol) ',inherited-symbolŤ‰ (documentation ',inheriting-symbol 'function) ,doc-string))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 1 :LENGTH-IN-BYTES 800 :AUTHOR "LFW" :CREATION-DATE 2673470266 :QFASLP NIL :LENGTH 800 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "EMPTY" :TYPE "CHART" :VERSION 1) ; -*- mode:LISP; package:(org) ; base: 10. -*- ŤŤŤ; This file was generated by the ORG program. It contains the Ť; information necessary to reconstruct a chart from scratch. Ť; Ť; Modify this file only if you really know what you're doing.Ť; It's much better to run ORG, then load this file, modify it,Ť; and save out the preferred version.ŤŤ; This is the top node:ŤŤ(setq N0608 Ť (make-instance 'node Ť ':pane *chart-pane Ť ':opened? T Ť ':attributesŤ '(("Name" "anonymous") ("Title" ORG:*NEEDS-FILLING-IN) ("Location" ORG:*NEEDS-FILLING-IN)) Ť ':justification ':CENTER Ť ':extra-width 10. Ť ':vertical-separation 10. Ť ':horizontal-separation 10.))ŤŤ(send *chart-pane ':set-top-node N0608)Ť(send N0608 ':set-pane *chart-pane)ŤŤŤ; Th-th-that's all, folks!LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 11 :LENGTH-IN-BYTES 11110 :AUTHOR "george" :CREATION-DATE 2686608354 :QFASLP NIL :LENGTH 11110 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "FANCIER-LISPM" :TYPE "LISP" :VERSION 3) ;;;-*- Mode:LISP; Package:USER; Fonts:(MEDFNT HL12I); Patch-File:T; Base:10 -*-Ť;1;; ESMITH's LispM init file.* ŤŤ;1;; WARNING FROM THE SAGE OF THE INIT FILE, The Hon. I. M. Never Donne, DOA*Ť;1;;*Ť;1;; It is UNWISE to EXCESSIVELY MODIFY one's LISPM environment, inasmuch*Ť;1;; as one may not always be at one's HOME SITE, and may thus, sadly, be UNABLE*Ť;1;; TO ACCESS the customized functions one has grown to take for granted. In*Ť;1;; particular, attempting to modify the INIT file as the first action after login*Ť;1;; indicates INCIPIENT "BRAIN-DAMAGE". Now, go off and eat your SPAM.*ŤŤ;1;; Define functions to facilitate initial user query which follows*Ť(DEFSUBST SORRY-START-AGAIN (USER HOST)Ť (LOGOUT)Ť (LOGIN USER HOST))ŤŤ(DEFMACRO DEFAULT-USER-NAME ()Ť `(READ-FROM-STRINGŤ (%P-CONTENTS-OFFSET (CDAR *DEFAULT-PATHNAME-DEFAULTS*) 3)))ŤŤ(DEFMACRO DEFAULT-USER-HOST ()Ť `(%P-CONTENTS-OFFSET (CDAR (LAST *DEFAULT-PATHNAME-DEFAULTS*)) 1))ŤŤ(DEFSUBST STRING-SUBSTITUTE-ONCE (OLD-SUBSTRING NEW-SUBSTRING MAIN-STRING)Ť (STRING-APPENDŤ (SUBSTRING MAIN-STRING 0 (STRING-SEARCH OLD-SUBSTRING MAIN-STRING))Ť NEW-SUBSTRINGŤ (SUBSTRING MAIN-STRING (PLUS (STRING-SEARCH OLD-SUBSTRING MAIN-STRING)Ť‰‰ ‰ (LENGTH OLD-SUBSTRING))Ť ‰ (LENGTH MAIN-STRING))))ŤŤ;1;; Offer to patch up this init file, IN ADVANCE OF loading any more of it*Ť(WHEN (Y-OR-N-P "Modify LISPM.INIT ?")Ť (FORMAT T (STRING-APPEND "~%Entering ZMacs to edit "Ť‰‰‰ (default-user-host)Ť‰‰‰ ": "Ť‰‰‰ (default-user-name)Ť‰‰‰ "; LISPM.LISP"))Ť (FORMAT T "~%Press any key except -[Abort] to proceed ...")Ť (TYI)Ť (LET* ((LISPM-INIT-NAMESTRINGŤ‰ (STRING-APPEND (DEFAULT-USER-HOST) ": "Ť‰‰‰ (DEFAULT-USER-NAME) "; "Ť‰‰‰ "LISPM.LISP#>"))Ť‰ (LISPM-INIT-PATHNAME (FS:PARSE-PATHNAME LISPM-INIT-NAMESTRING)))Ť (ED LISPM-INIT-PATHNAME)Ť (FORMAT T (STRING-APPEND "~%Compiling changes to " LISPM-INIT-NAMESTRING))Ť (COMPILE-FILE LISPM-INIT-PATHNAMEŤ‰‰ :OUTPUT-FILENAME (STRING-SUBSTITUTE-ONCE ".LISP"Ť‰‰‰‰‰‰‰ ".INIT"Ť‰‰‰‰‰‰‰ LISPM-INIT-NAMESTRING)Ť‰‰ :SET-DEFAULT-PATHNAME NIL)Ť (SORRY-START-AGAIN1 *(DEFAULT-USER-NAME) (DEFAULT-USER-HOST))))ŤŤ;1;; Make local machine aware of any changes to network configuration since last boot*Ť(UPDATE-SITE-CONFIGURATION-INFO)ŤŤ;1;; reader macro which causes font changes to be ignored* 1in release 1.2 and below*Ť(WHEN (< (SI:GET-SYSTEM-VERSION) 95.)Ť (SET-SYNTAX-MACRO-CHAR #\EPSILONŤ #'(LAMBDA (SPLICE STREAM &AUX (CHAR (SEND STREAM ':TYI)))Ť‰(SELECTQ CHARŤ‰ ((#/0 #/1 #/2 #/3 #/4 #/5 #/6 #/7 #/8 #/9 #/*)Ť‰ (VALUES SPLICE NIL T))Ť‰ (:OTHERWISE (SEND STREAM ':UNTYI CHAR)Ť‰‰ (VALUES (INTERN (STRING #\EPSILON) NIL NIL)))))))ŤŤ;1;;Now we can use fontified comments!*ŤŤ(PUSH '(PKG-GOTO) LOGOUT-LIST)ŤŤ(MAPCAR 'LOGIN-EVALŤ'((SETQ ZWEI:*CHECK-UNBALANCED-PARENTHESES-WHEN-SAVING* T)Ť (SETQ ZWEI:*INITIAL-MINOR-MODES* '(ZWEI:ATOM-WORD-MODE))Ť (SETQ ZWEI:LISP-MODE-HOOK 'ZWEI:ELECTRIC-SHIFT-LOCK-IF-APPROPRIATE)Ť (SETQ BASE 10. IBASE 10. ZWEI:BASE 10. ZWEI:IBASE 10. *NOPOINT T)Ť (SETQ ZWEI:*FILE-VERSIONS-KEPT* 4 ZWEI:*KILL-INTERVAL-SMARTS* T)Ť ;1;; Pretty printing* 1for release 1.2 and below*Ť (DEFF PP 'GRIND-TOP-LEVEL)Ť (DEFUN G (X) (GRIND-TOP-LEVEL X))Ť (DEFUN TV:MAKE-IDLE-MESSAGE (MINUTES)Ť (COND ((< MINUTES 60.)Ť (FORMAT NIL "Goofing off for ~D minute~:P" MINUTES))Ť (T (LET ((HOURS (// MINUTES 60.)))Ť (IF (> HOURS 12.) (SETQ HOURS (- HOURS 12.)))Ť (FORMAT NIL "User absent or asleep for ~d hr ~d min~:P"Ť hours (- minutes (* 60. hours)))))))Ť))ŤŤ;;; 1Make WHO-LINE DOC window readable*Ť(SEND TV:WHO-LINE-DOCUMENTATION-WINDOW ':SET-FONT-MAP '(HL10B))ŤŤ;;; 1Make a selected symbol globally visible* Ť(DEFUN GLOBAL (X)Ť (LET* ((STRING-NAME (STRING X)) GLOBAL-ATOM)Ť (SETQ GLOBAL-ATOM (INTERN STRING-NAME "GLOBAL"))Ť (IF (FBOUNDP GLOBAL-ATOM)Ť‰NIL 1;;; it is already globalized*Ť (GLOBALIZE X))))ŤŤ;1;; How big a machine do we have ?*Ť(ROOM)ŤŤ;1;; Has anybody been glomming memory cards in the dark of night ?*Ť(COND ((< (// (SYS:SYSTEM-COMMUNICATION-AREA SYS:%SYS-COM-MEMORY-SIZE) #o2000)Ť‰ 256.)Ť (PRINT "Someone has raided the memory.")Ť (TV:BEEP)))ŤŤ;1;;* 1the postman always rings twice ?*Ť(LET ((MAILFILE (STRING-APPEND (default-user-host)Ť‰‰‰ ": "Ť‰‰‰ (default-user-name)Ť‰‰‰ "; mail.text")))Ť (COND ((PROBEF MAILFILE)Ť‰ (TV:BEEP)Ť‰ (FORMAT T "You have mail, please use ZMAIL to read it.")Ť‰ (COND ((Y-OR-N-P "Look at mail? ")Ť‰‰(FS:VIEWF MAILFILE)Ť‰‰(COND ((YES-OR-NO-P "Delete Mail file? ")Ť‰‰ (FS:DELETEF MAILFILE))))))))ŤŤ;1;; Tell all about current state of software, including microcode and world loads*Ť(WHEN (Y-OR-N-P "Display (microcode) bands and load patches ? ")Ť (PRINT-DISK-LABEL)Ť (LOAD-PATCHES ':NOSELECTIVE)Ť (PRINT-SYSTEM-MODIFICATIONS))ŤŤ;1;; Predicate to facilitate "applicative iteration" using MAPCAR*Ť(DEFMACRO MAKE-COPIES-OF (S-EXPR COUNT)Ť `(MAKE-SEQUENCE 'LIST ,COUNT :INITIAL-ELEMENT ,S-EXPR))ŤŤ;1;; Boolean test for existance of named entry on master list of loaded systems*Ť(DEFSUBST IS-LOADED-SYSTEM (SYSTEM-NAME)Ť (CAR (MEMBER TŤ‰ (MAPCAR 'COMPARE-SYSTEM-NAMEŤ‰‰ SI:*SYSTEMS-LIST*Ť‰‰ (MAKE-COPIES-OF SYSTEM-NAME (LENGTH SI:*SYSTEMS-LIST*))))))ŤŤ(DEFSUBST COMPARE-SYSTEM-NAME (LOCATIVE SYSTEM-NAME)Ť (IF (EQUAL (DATA-TYPE LOCATIVE) 'DTP-ARRAY-POINTER)Ť (EQUAL (STRING SYSTEM-NAME)Ť‰ (STRING-UPCASE (%P-CONTENTS-OFFSET LOCATIVE 2)))Ť NIL))ŤŤ;1;; Load systems which are sometimes missing in standard load*Ť(UNLESS (OR (ASSOC #/K TV:*SYSTEM-KEYS*) ;1;; alternate tests for system existence*Ť‰ (CAR (MEMBER ':KERMIT SI:*SYSTEMS-LIST*))Ť‰ (IS-LOADED-SYSTEM 'KERMIT))Ť (MAKE-SYSTEM 'KERMIT)) ;1;; Kermit serial file transfer utility*ŤŤ;1;; Offer to load miscellaneous simple utility packages*Ť(WHEN (Y-OR-N-P "Load quick stats ?")Ť (LOAD (STRING-APPEND (default-user-host)Ť‰‰ ": "Ť‰‰ (default-user-name)Ť‰‰ "; quick-stats")))ŤŤ;1;; Cut intimidating *"1High-Speed-Godzilla*-M1ouse*"1 down to size...*Ť(SETQ TV:MOUSE-FAST-MOTION-SPEED 25.)Ť(SETQ TV:MOUSE-FAST-MOTION-CROSS-SIZE 20.)Ť(SETQ TV:MOUSE-FAST-MOTION-CROSS-TIME 1000.)ŤŤ;1;; set up default* 1font map, for what it is worth*Ť(SEND TERMINAL-IO ':SET-FONT-MAPŤ '(FONTS:MEDFNB FONTS:CPTFONT FONTS:BIGFNT FONTS:5X5))Ť(SEND TERMINAL-IO ':SET-CURRENT-FONT 'FONTS:MEDFNB)ŤŤ;1; Zwei (ie, ZMACS*) 1customizations.*Ť(PKG-GOTO 'ZWEI)ŤŤ(PROGN 'COMPILEŤŤ(DEFCOM COM-INDENT-SEXPŤ"Indent the following s-expression. Each line that starts withinŤ the s-expression is indented for Lisp, assuming that the lineŤ the current set point is on is NOT adjusted. This command willŤ indent the first line as well."Ť ()Ť (COM-INDENT-FOR-LISP)Ť (LET ((BP1 (OR (BEG-LINE (POINT) 1) (BARF)))Ť‰(BP2 (OR (FORWARD-SEXP (POINT)) (BARF))))Ť (AND (BP-< BP1 BP2)Ť‰ (WITH-UNDO-SAVE ("Indent sexp" BP1 BP2 T)Ť‰‰‰ (INDENT-INTERVAL-FOR-LISP BP1 BP2 T))))Ť DIS-TEXT)ŤŤ(DEFCOM COM-FILL-PARAGRAPH Ť"Fill (or adjust) this (or next) paragraph. This is disabled inŤ LISP mode. Set point stays the same. A positive argument meansŤ to adjust rather than fill."Ť ()Ť (IF (EQ *MAJOR-MODE* 'LISP-MODE)Ť NIL 1;;; no fill paragraph while in LISP mode*.Ť (LET ((INT (PARAGRAPH-INTERVAL (POINT))))Ť (FILL-INTERVAL INT NIL T (AND *NUMERIC-ARG-P* (PLUSP *NUMERIC-ARG*)))))Ť DIS-TEXT)ŤŤ1;;;* 1MODIFIED Append To Buffer which completes buffer names* 1(same as regular, but* ...)Ť(DEFCOM COM-PRE-APPEND-TO-BUFFERŤ"Append region to the specified buffer. The name of the buffer isŤ read from the keyboard; it is completed normally. With an argument,Ť we /"prepend/" instead. Inserts the text at that buffer's point,Ť but when prepending leaves the point before the inserted text."Ť ()Ť (REGION (BP1 BP2)Ť‰ (LET ((POINT) (MARK)Ť‰ (BUFFER (READ-BUFFER-NAMEŤ‰‰‰ (IF *NUMERIC-ARG-P* "Prepend to buffer:" "Append to buffer:")Ť‰‰‰ NIL NIL)))Ť‰ (COND ((EQ BUFFER *INTERVAL*)Ť‰‰ (BARF "That is the current buffer.")))Ť‰ 1;;;Try to find a window pointing to this buffer and use its point and mark*Ť‰ (DO ((WL *WINDOW-LIST* (CDR WL))Ť‰‰(W))Ť‰ ((NULL WL)Ť‰‰(SETQ POINT (BUFFER-SAVED-POINT BUFFER)Ť‰‰ MARK (BUFFER-SAVED-MARK BUFFER)))Ť‰ (COND ((EQ (WINDOW-INTERVAL (SETQ W (CAR WL))) BUFFER)Ť‰‰ (SETQ POINT (WINDOW-POINT W) MARK (WINDOW-MARK W))Ť‰‰ (RETURN NIL))))Ť‰ (MOVE-BP MARK (INSERT-INTERVAL POINT BP1 BP2 T))Ť‰ (OR *NUMERIC-ARG-P* (SWAP-BPS MARK POINT)) Ť‰ (MUST-REDISPLAY-OTHER-WINDOWS BUFFER *WINDOW* DIS-TEXT))) Ť DIS-NONE)ŤŤ) 1;;; end of (PROGN 'COMPILE ...* 1formŤŤ;;;Set up some ZMacs commands for me* (1most of these are Control-Shift or Meta-Shift).*Ť(LOGIN-EVALŤ (set-comtab-return-undo *standard-comtab*Ť‰‰ '(#\ctrl-altmode com-expand-onlyŤ‰‰ #\super-ctrl-c com-microcompile-defunŤ‰ ‰ #\Hyper-Ctrl-D com-quick-disassembleŤ‰‰ #\ctrl-top-e com-evaluate-defunŤ‰‰ #\Super-altmode com-make-word-abbrevŤŤ 1;;; Set up hand keys to work like arrow keys*Ť‰‰‰ #\hand-up com-up-real-line Ť‰‰‰ #\hand-down com-down-real-line Ť‰‰‰ #\hand-left com-backwardŤ‰‰‰ #\hand-right com-forwardŤŤ‰‰‰ 1;;; Make Roman keys do useful things*Ť‰‰‰ #\roman-i com-backward-paragraphŤ‰‰‰ #\roman-ii com-forward-paragraphŤ‰‰‰ #\roman-iii com-beginning-of-lineŤ‰‰‰ #\roman-iv com-end-of-lineŤŤ‰‰‰ 1;;; Make delete do rubouts*Ť‰‰‰ #\delete com-ruboutŤ‰ Ť 1;;; add various EVAL, COMPILE and MICROCOMPILE options*Ť‰‰ #\Control-//‰ com-Evaluate-RegionŤ‰‰‰ #\Meta-//‰ com-Compile-RegionŤ‰‰‰ #\Control-Meta-// com-Microcompile-RegionŤ‰‰‰ #\Control-/`‰ com-Evaluate-BufferŤ‰‰‰ #\Meta-/`‰ com-Compile-BufferŤ‰‰‰ #\Control-Meta-/` com-Microcompile-BufferŤ‰‰‰ #\Control-{‰ com-Evaluate-Buffer-Changed-SectionsŤ‰‰‰ #\Meta-{‰ com-Compile-Buffer-Changed-SectionsŤ‰‰‰ #\Control-Meta-{ com-Microcompile-Buffer-Changed-SectionsŤ‰‰‰ #\Control-}‰ com-Evaluate-Changed-SectionsŤ‰‰‰ #\Meta-}‰ com-Compile-Changed-SectionsŤ‰‰‰ #\Control-Meta-} com-Microcompile-Changed-SectionsŤ‰‰‰ #\Control-/'‰ com-Evaluate-Mini-Buffer)))Ť‰ Ť(LOGIN-EVALŤ‰ (set-comtab *ZMacs-Control-X-Comtab*Ť‰‰ '(#/A‰‰‰com-Pre-Append-To-Buffer)))Ť‰ Ť(LOGIN-EVALŤ (setq Lisp-Mode-HookŤ‰ #'(lambda ()Ť‰ (turn-on-mode 'Electric-Shift-Lock-Mode)Ť‰ (turn-on-mode 'Return-Indents-Mode)Ť‰ (turn-on-mode 'Electric-Font-Lock-Mode))))Ť‰ Ť(LOGIN-EVALŤ (setq Text-Mode-HookŤ‰ #'(lambda ()Ť‰ (turn-off-mode 'Electric-Shift-Lock-Mode)Ť‰ (turn-on-mode 'Any-Bracket-Mode))))ŤŤ1;;; Leave Lisp Listener in a reasonable context*Ť(PKG-GOTO 'USER)ŤŤ;1;; LOGIN-EVAL this last, so that when logging out, it will be done first.*Ť(LOGIN-EVAL '(ZWEI:SAVE-ALL-FILES))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 24 :LENGTH-IN-BYTES 23808 :AUTHOR "MDS" :CREATION-DATE 2712055842 :QFASLP NIL :LENGTH 23808 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "FORTRAN-CALL" :TYPE "LISP" :VERSION 1) #| -*- Mode:LISP; Package:(FCALL global); Fonts:(cptfontb); Base:10 -*-ŤŤ Copyright LISP Machine, Inc. 1985Ť See filename "Copyright" forŤ licensing and release information.ŤŤA self-contained example of how to build an interprocessorŤFORTRAN-CALL library mechanism. 5/18/85 13:16:28 -George CarretteŤŤThe goal would be to have a system such that if,ŤŤWe define:ŤŤ(DEFINE-FORTRAN-LIBRARY "documentation"Ť :executable-image "/usr/flib/streamlib"ŤŤ :subroutine (FFT (X :REAL-ARRAY)Ť‰‰ (Y :REAL-ARRAY)Ť‰‰ (N :INTEGER))ŤŤ :subroutine (IFT (X :REAL-ARRAY)Ť‰‰ (Y :REAL-ARRAY)Ť‰‰ (N :INTEGER)))ŤŤŤThen:Ť (GENERATE-MAIN-PROGRAM ') ==> causes a main program in "C" to be generated.Ť (GENERATE-EXECUTABLE ') ==> compiles the "C" program and calls the linker.ŤŤBefore a subroutine may be called there must be an executable program startedŤup on the connected shared processor, to do this we would instantiated aŤjob, duty or processing thread, whatever you want to call it.ŤŤPrequisite to run:ŤŤ (SETQ *ABLE* (INSTANTIATE-FORTRAN-LIBRARY '))ŤŤŤTo run:ŤŤ (SETQ X (MAKE-ARRAY 16 :ELEMENT-TYPE 'FLOAT))Ť (SETQ Y (MAKE-ARRAY 16 :ELEMENT-TYPE 'FLOAT))ŤŤ (SEND *ABLE* :CALL "FFT" X Y 16)ŤŤA simple :CALL such as the above would not return until the computationŤon the coprocessor had completed. However, that need not be the case,Ťwe could say instead:ŤŤ (SEND *ABLE* :CO-CALL "FFT" X Y 16)ŤŤ Which would return immediately. To found out when the computation isŤ complete and the values in the arrays X and Y are consistent we sendŤ a message:ŤŤ (EQ (SEND *ABLE* :STATE) :DONE) => true if the computation is complete.ŤŤAn example of doing two things at the same time would be:ŤŤ (LET ((DONE NIL))Ť (PROCESS-RUN-FUNCTION "symbolic way"Ť #'(lambda ()Ť (find-the-answer-using-AI-techniques X Y Z)Ť (setq done t)))Ť (SEND *ABLE* :CO-CALL "SOLVE9" X Y Z)Ť (PROCESS-WAIT "thinking" #'(lambda () (or done (eq :done (send *able* :STATE)))))Ť (if doneŤ (format t "The answer was found first using AI techniques")Ť (format t "The answer was found first using the old FORTRAN numerical way")))ŤŤŤŤŤImplementation:Ť fort.h A file of declarations shared by all files.Ť fmain.c The main subroutine, which opens the syncronizing device,Ť initializes pointers to shared memory, and calls fexecŤ for each subroutine call request.Ť fexec.c This gets an opcode from shared memory, and calls fload toŤ get a link (dynamically or statically) to a FORTRAN subroutine.Ť It then sets up an argument vector by normalizing the arglistŤ in shared memory by the base of shared memory in the Ť user process. The linked FORTRAN subroutine is then called,Ť and a shared memory location is set to zero to indicateŤ completion of the subroutine.Ť fload.c In our example this is a static linking of an array ofŤ pointers to FORTRAN subroutines.Ť ftable.c The dispatch table of FORTRAN subroutines.Ť flib.f The fortran subroutines.ŤŤNote: In the example we do not address the issue of interlockingŤ of shared memory resources such as would be needed withŤ multiple instantiations of fortran libraries in or acrossŤ lambda processors.ŤŤ|#ŤŤŤ(defmacro DEFINE-FORTRAN-LIBRARY (name documentation &rest body)Ť `(*define-fortran-library ',name ,documentation ',body))ŤŤ(defun *define-fortran-library (name documentation arguments)Ť (when (record-source-file-name name 'define-fortran-library)Ť (setf (function-documentation name 'fortran-library) documentation)Ť (do ((l arguments (cddr l))Ť‰ (plist))Ť‰((null l)Ť‰ (setf (get name 'fortran-library) plist))Ť (ecase (car l)Ť‰((:unix-filename-append :executable-image :link-table :files)Ť‰ (setf (getf plist (car l)) (cadr l)))Ť‰(:subroutineŤ‰ (let ((subroutine (if (atom (cadr l)) (list (cadr l)) (cadr l))))Ť‰ (push subroutine (getf plist :subroutines))))))))ŤŤ(defflavor fortran-imageŤ‰ ((name nil) sync-stream (processor nil)Ť‰ eval-server-processŤ‰ (eval-server-output "")Ť‰ commandŤ‰ return-valuesŤ‰ being-calledŤ‰ (flushed nil)Ť‰ opcode-pointer)Ť‰ ()Ť :initable-instance-variablesŤ :settable-instance-variables)ŤŤŤ(defmethod (fortran-image :print-self) (stream &rest ignored)Ť (format stream "#"Ť‰ name processorŤ‰ eval-server-output))ŤŤ(defun instantiate-fortran-library (name &optional (port-number 5))Ť ;; in fact the port number should be auto incrementedŤ (check-arg name (fortran-libraryp name) "a fortran library")Ť (let ((port (open (format nil "UNIX-STREAM-~D:" port-number)))Ť‰(proc (attached-unix-host))Ť‰(os (make-array 200 :fill-pointer 0 :element-type 'string-char))Ť‰(command (format nil "~a //dev//ttyl~D"Ť‰‰‰ (send (fortran-library-pathname name :executable-image)Ť‰‰‰ :string-for-host)Ť‰‰‰ port-number)))Ť (let ((obj (make-instance 'fortran-imageŤ‰‰‰ :name nameŤ‰‰‰ :sync-stream portŤ‰‰‰ :processor procŤ‰‰‰ :eval-server-output osŤ‰‰‰ :command command)))Ť (send obj :start-process)Ť (process-wait "unix startup"Ť‰‰ #'(lambda (x)Ť‰‰‰(> (length (send x :eval-server-output))Ť‰‰‰ (length (send x :command))))Ť‰‰ obj)Ť obj)))ŤŤŤ(defmethod (fortran-image :start-process) ()Ť (setq eval-server-processŤ‰(process-run-functionŤ‰ (format nil "fortran library ~A" name)Ť‰ #'fortran-image-simple-unix-evalŤ‰ processorŤ‰ commandŤ‰ (make-string-output-stream eval-server-output)Ť‰ self)))ŤŤŤ(defun fortran-image-simple-unix-eval (processor command output done)Ť (simple-unix-eval processor command output)Ť (send done :set-flushed t))ŤŤŤ(defvar *shared-memory-type-array* ())ŤŤ(defvar *value-free-pointer* 0)ŤŤ(defun allocate-value-space ()Ť ;; this is where interlocking between processors might happen.Ť (or (and *shared-memory-type-array*Ť‰ (= (length *shared-memory-type-array*)Ť‰ (quotient (length si:*global-shared-memory-16*) 2)))Ť (setq *shared-memory-type-array*Ť‰ (make-array (quotient (length si:*global-shared-memory-16*) 2))))Ť (setq *value-free-pointer* 0))ŤŤ(defsetf read-value write-value)ŤŤ(defun read-value (location type)Ť "Read a value and do representation conversion"Ť (let ((n (dpb (aref si:*global-shared-memory-16* (1+ (ash location 1)))Ť‰‰#o2020Ť‰‰(aref si:*global-shared-memory-16* (ash location 1)))))Ť (ecase typeŤ (:realŤ (68000-float->lispm n))Ť (:integerŤ (signed-68000->lispm n))Ť (nilŤ n))))ŤŤ(defun write-value (location type value)Ť "Write a value of a given type into the shared location, doing representationŤconversion for types of :REAL and :INTEGER."Ť (let ((n (ecase typeŤ‰ (:realŤ‰ (lispm-float->68000 value))Ť‰ (:integerŤ‰ (signed-lispm->68000 value)))))Ť (setf (aref si:*global-shared-memory-16* (ash location 1))Ť‰ (ldb #o0020 n))Ť (setf (aref si:*global-shared-memory-16* (1+ (ash location 1)))Ť‰ (ldb #o2020 n))Ť (setf (aref *Shared-memory-type-array* location) type)))ŤŤ(defun push-value (value type)Ť (setf (read-value *value-free-pointer* type) value)Ť (incf *value-free-pointer*))ŤŤ(defun read-known-value (location)Ť (read-value location (aref *shared-memory-type-array* location)))ŤŤŤ(defun dump-value-space (&optional (end (length *shared-memory-type-array*)))Ť (format t "~&Location Type Value~%")Ť (dotimes (j end)Ť (let ((type (aref *shared-memory-type-array* j)))Ť (format t "~4D ~7A ~S~%" J TYPE (read-value j type)))))Ť‰ ŤŤ(defmethod (fortran-image :co-call) (subroutine &rest arguments)Ť (let* ((subroutines (getf (get name 'fortran-library) :subroutines))Ť‰ (desc (ass #'string-equal subroutine subroutines)))Ť (or desc (ferror nil "No subroutine called ~A in fortran library ~A"Ť‰‰ subroutine name))Ť (setq being-called desc)Ť (let ((nargs (length arguments))Ť‰ (opcode (1+ (find-position-in-list desc subroutines)))Ť‰ (argspointer))Ť (or (= nargsŤ‰ (length (cdr desc)))Ť‰ (ferror nil "Fortran subroutine ~A expects ~D argument~p, got ~D"Ť‰‰ subroutineŤ‰‰ (length (cdr desc))Ť‰‰ (length (cdr desc))Ť‰‰ nargs))Ť (allocate-value-space)Ť (setq opcode-pointer *value-free-pointer*)Ť (push-value opcode :integer)Ť (push-value nargs :integer)Ť (setq argspointer *value-free-pointer*)Ť (incf *value-free-pointer* nargs)Ť (setq return-values nil)Ť (do ((actuals arguments (cdr actuals))Ť‰ (formals (cdr desc) (cdr formals))Ť‰ (j 0 (1+ j)))Ť‰ ((null actuals))Ť‰(let ((pointer *value-free-pointer*)Ť‰ (datatype (cadr (car formals)))Ť‰ (data (car actuals)))Ť‰ (if (typep data 'sequence)Ť‰ (push (list data datatype pointer) return-values))Ť‰ (setf (read-value (+ argspointer j) :integer) pointer)Ť‰ (ecase datatypeŤ‰ ((:real :integer)Ť‰ (push-value (if (typep data 'sequence)Ť‰‰‰ (elt data 0)Ť‰‰‰ data)Ť‰‰‰ datatype))Ť‰ ((:real-array :integer-array)Ť‰ (let ((element-type (cadr (assq datatype '((:real-array :real)Ť‰‰‰‰‰‰‰(:integer-array :integer))))))Ť‰ (dotimes (k (length data))Ť‰‰ (push-value (elt data k) element-type)))))))Ť (send sync-stream :tyo #/X)Ť (send sync-stream :tyo 13)Ť (send sync-stream :force-output)Ť )))ŤŤŤ(defmethod (fortran-image :stop) ()Ť (cond ((not flushed)Ť‰ (send sync-stream :tyo #/S)Ť‰ (send sync-stream :tyo 13)Ť‰ (send sync-stream :force-output)Ť‰ (process-wait "unix to stop"Ť‰‰ #'(lambda (x) (send x :flushed))Ť‰‰ self)Ť‰ (close sync-stream)Ť‰ (setq sync-stream nil)Ť‰ (setq eval-server-process nil)))Ť self)ŤŤ(defmethod (fortran-image :state) ()Ť (if (zerop (read-value opcode-pointer :integer)) :done :computing))ŤŤŤ(defmethod (fortran-image :call) (subroutine &rest arguments)Ť (lexpr-send self :co-call subroutine arguments)Ť (process-wait "computing" #'(lambda (x) (eq :done (send x :state))) self)Ť (send self :get-return-values))ŤŤ(defmethod (fortran-image :get-return-values) ()Ť (dolist (item return-values)Ť (let ((sequence (car item))Ť‰ (pointer (caddr item)))Ť (dotimes (j (length sequence))Ť‰(setf (elt sequence j) (read-known-value (+ pointer j)))))))ŤŤŤ(compile-flavor-methods fortran-image)ŤŤŤ(defun simple-unix-eval (host command &optional (stream standard-output))Ť (with-open-stream (s (chaos:open-stream hostŤ‰‰‰‰‰ (format nil "EVAL ~a" command)))Ť (format stream "~&% ~A~%" command)Ť (do ((c (send s ':tyi) (send s ':tyi)))Ť‰((null c))Ť (send stream ':tyoŤ‰ (selectq cŤ‰ ((#o12 #o15) #\return)Ť‰ (#o11 #\tab)‰‰ Ť‰ (t c))))))ŤŤ(defun attached-unix-host ()Ť "Returns host object for attached unix-host if it exits otherwise NIL"Ť;; Relevant variable:Ť;; si:*other-processors* list of structures of type SI:OTHER-PROCESSORŤ (dolist (op si:*other-processors*)Ť (let ((host (SI:GET-HOST-FROM-ADDRESSŤ‰‰ (si:%processor-conf-chaos-address (si:op-proc-conf op))Ť‰‰ ':CHAOS)))Ť (if (typep host 'fs:unix-host)Ť‰ (return host)))))ŤŤ;; data conversion:Ť;; In the lisp environment all 68000 data is manipulated as 32 bit integers.ŤŤ(defun 68000-byteswap (integer)Ť (dpb (ldb #o0010 integer)Ť #o3010Ť (dpb (ldb #o1010 integer)Ť‰ #o2010Ť‰ (dpb (ldb #o2010 integer)Ť‰‰ #o1010Ť‰‰ (ldb #o3010 integer)))))ŤŤ(defun signed-lispm->68000 (integer)Ť (68000-byteswap integer))ŤŤ(defun signed-68000->lispm (integer)Ť (let ((n (68000-byteswap integer)))Ť (if (bit-test 1_31 n)Ť‰(- n 1_32)Ť n)))ŤŤŤ(defun 68000-float->lispm (x)Ť "Take 32bits, a 68000 float, and return a lisp float object"Ť (// (* (expt -1 (ldb #o3701 x))Ť‰ (expt 2.0 (- (ldb #o3007 x) #o100))Ť‰ (+ (ldb #o2010 x)Ť‰ (ash (+ (ldb #o1010 x)Ť‰‰ (ash (ldb #o0010 x)Ť‰‰‰ 8))Ť‰‰ 8)))Ť #o100000000))ŤŤŤ(defun lispm-float->68000 (x &aux sign exp frac)Ť "Take a lispmachine floating point number and return 32 bits suitable for the 68000"Ť (cond ((zerop x)Ť‰ (return-from lispm-float->68000 0))Ť‰((< x 0.0)Ť‰ (setq sign 1)Ť‰ (setq x (- x)))Ť‰('elseŤ‰ (setq sign 0)))Ť (etypecase xŤ (short-floatŤ (setq exp (+ (- (si:%short-float-exponent x) #o200) #o100))Ť (setq frac (ash (si:%short-float-mantissa x)Ť‰‰ (- 23 16))))Ť (single-floatŤ (setq exp (+ (- (si:%single-float-exponent x) #o2000) #o100))Ť (setq frac (ash (si:%single-float-mantissa x)Ť‰‰ (- 23 30)))))Ť (if (or (< exp 0)Ť‰ (> exp #o177))Ť (ferror nil "Exponent too big to represent in 68000: ~S" x))Ť (dpb sign #o3701Ť (dpb exp #o3007Ť‰ (dpb (ldb #o0010 frac) #o2010Ť‰‰ (dpb (ldb #o1010 frac) #o1010Ť‰‰ (ldb #o2010 frac))))))ŤŤŤŤ;; generation of code and linking.ŤŤŤ(defun fortran-libraryp (name)Ť (get name 'fortran-library))ŤŤ(defun fortran-library-pathname (name type &optional (to-host (attached-unix-host)))Ť (let ((p (fortran-libraryp name)))Ť (let ((l (getf p type))Ť‰ (a (getf p :unix-filename-append)))Ť (if (and (symbolp a) (boundp a))Ť‰ (setq a (symeval a)))Ť (cond ((atom l)Ť‰ (fs:parse-pathname (if a (string-append a l) l) to-host))Ť‰ ('elseŤ‰ (mapcar #'(lambda (x) (fs:parse-pathname (if a (string-append a x) x)Ť‰‰‰‰‰‰ to-host))Ť‰‰ l))))))ŤŤ(defun generate-main-program (name &aux plist subroutines)Ť "generates the link table for fortran library NAME"Ť (check-arg name (setq plist (fortran-libraryp name)) "a fortran library")Ť (setq subroutines (mapcar #'(lambda (x)Ť‰‰‰‰(if (> (length (cdr x)) 9)Ť‰‰‰‰ (ferror nilŤ‰‰‰‰‰ "Too many arguments in subroutine: ~S"Ť‰‰‰‰‰ x))Ť‰‰‰‰(string-downcase (car x)))Ť‰‰‰ (getf plist :subroutines)))Ť (with-open-file (s (fortran-library-pathname name :link-table)Ť‰‰ :out)Ť (format s "~Ť ~70,,,'*~Ť ~%~70< * Automatically generated C code for the FORTRAN link ~;*~>~Ť ~%~70< * Compiled from ~S by ~S ~;*~>~Ť ~%~70< * ~A ~;*~>~Ť ~%~71,,,'*< *~;//~>~Ť ~%~%#include /"fort.h/"~2%~Ť ~%~{int ~a();~%~}~Ť ~%int (*ftable[])() = {noop,~%~{ ~a~^,~%~}};~%"Ť‰ nameŤ‰ si:user-idŤ‰ (time:print-current-date nil)Ť‰ subroutinesŤ‰ subroutinesŤ‰ )))ŤŤŤŤ(defun generate-executable (name)Ť (check-arg name (fortran-libraryp name) "a fortran library")Ť (flet ((hosty (x) (send x :string-for-host)))Ť (simple-unix-eval (attached-unix-host)Ť‰‰ (format nilŤ‰‰‰ "cc -o ~a ~{~a ~} ~a -lshare -lF77 -lI77"Ť‰‰‰ (hosty (fortran-library-pathname name :executable-image))Ť‰‰‰ (mapcar #'hosty (fortran-library-pathname name :files))Ť‰‰‰ (hosty (fortran-library-pathname name :link-table))))))ŤŤ;; the exampleŤŤ(defvar *udir* "//usr//gjc//fort//")ŤŤ(define-fortran-library example "an example"Ť :subroutine (VADD (X :real-array)Ť‰‰ (y :real-array)Ť‰‰ (z :real-array)Ť‰‰ (n :integer))Ť :subroutine (vmult (X :real-array)Ť‰‰ (y :real-array)Ť‰‰ (z :real-array)Ť‰‰ (n :integer))Ť :subroutine (vprint (x :real-array)Ť‰‰ (n :integer))Ť :unix-filename-append *udir*Ť :executable-image "example"Ť :link-table "ftable.c"Ť :files ("fmain.o" "fload.o" "fexec.o" "flib.o"))ŤŤŤ(defun setup-unix-source-files (&optional (h (string-appendŤ‰‰‰‰‰ (send (attached-unix-host)Ť‰‰‰‰‰‰ :name)Ť‰‰‰‰‰ ":")))Ť (let (ofile)Ť (unwind-protectŤ‰(with-open-file (s (send (si:get-source-file-name 'setup-unix-source-files )Ť‰‰‰‰ :new-pathname :type "LISP" :version :NEWEST))Ť‰ (do ((line))Ť‰ ((null (setq line (readline s nil))))Ť‰ (cond ((string-equal "Filename:" lineŤ‰‰‰‰ :end2 (length "Filename:"))Ť‰‰ (when ofileŤ‰‰ (close ofile)Ť‰‰ (setq ofile nil))Ť‰‰ (setq line (string-append h *udir*Ť‰‰‰‰‰ (string-trimŤ‰‰‰‰‰ '(#\space)Ť‰‰‰‰‰ (substring lineŤ‰‰‰‰‰‰‰ (length "Filename:")))))Ť‰‰ (print line)Ť‰‰ (setq ofile (open line :direction :Output)))Ť‰‰ ((string-equal "||#" line :end2 (length "||#"))Ť‰‰ (when ofileŤ‰‰ (close ofile)Ť‰‰ (setq ofile nil)))Ť‰‰ (ofileŤ‰‰ (princ line ofile)Ť‰‰ (terpri ofile)Ť‰‰ (princ ".")))))Ť (and ofile (close ofile)))))ŤŤ#||ŤŤTo run the example, create a directory /usr/gjc/fortŤand put the files fmain.c, fload.c, fexec.c flib.fŤin it. (You can do that by running SETUP-UNIX-SOURCE-FILES)ŤŤThen generate ftable.c with the command (from lisp):ŤŤ (generate-main-program 'example)ŤŤThen compile all the C programs with the commands (from unix):Ť(or run the command % sh compile.sh)ŤŤ cc -c fmain.cŤ cc -c fload.cŤ cc -c fexec.cŤŤThen compile all the fortran functions with the command (from unix):ŤŤ f77 -c flib.fŤŤEverything may be linked together with the command (from lisp):ŤŤ (generate-executable 'example)ŤŤŤThen instantiate a runnable image of the library:ŤŤ (SETQ LIB (INSTANTIATE-FORTRAN-LIBRARY 'EXAMPLE))ŤŤ (setq x '(1.0 2.0 3.0))Ť (setq y '(1.0 2.0 3.0))Ť (setq z '(0.0 0.0 0.0))ŤŤŤ (SEND LIB :CALL "VMULT" X Y Z 3)ŤŤThen look at Z.ŤŤŤThe C and fortran code follows:ŤŤFilename: fort.hŤŤ/**************************************Ť * Copyright LISP Machine, Inc. 1985 *Ť * See filename "Copyright" for *Ť * licensing and release information. *Ť **************************************/ŤŤint noop();ŤŤint (*(fload()))();ŤŤint (*ftable[])();ŤŤFilename: fmain.cŤŤ/**************************************Ť * Copyright LISP Machine, Inc. 1985 *Ť * See filename "Copyright" for *Ť * licensing and release information. *Ť **************************************/ŤŤ#include ŤŤ#include ŤŤmain(argc,argv) int argc; char **argv;Ť{ int n,chan;Ť char c;Ť if (argc != 2) {printf("\n%s \n",argv[0]);exit(1);}Ť chan = open(argv[1],2);Ť if (chan < 0) {printf("\ncouldnt open syncronizing device: %s\n",argv[1]);Ť‰‰‰ exit(1);}Ť if (share_setup() < 0) {printf("share_setup failed");exit(1);}Ť while(1)Ť { n = read(chan,&c,1);Ť if (n != 1) {printf("\nsyncronizing device read failed\n");exit(1);}Ť if ( c == 'S') {printf("\nbeen told to stop\n");exit(1);}Ť if ( c == 'X') fexec(sharebase);}}ŤŤŤŤFilename: fexec.c ŤŤ/**************************************Ť * Copyright LISP Machine, Inc. 1985 *Ť * See filename "Copyright" for *Ť * licensing and release information. *Ť **************************************/ŤŤ/* execute a subroutine call out of arguments passed in the heap.Ť All arguments are call-by-reference, which is FORTRAN style.ŤŤ Heap format:Ť Ť 0 [Opcode]Ť 1 [Number-Of-Arguments]Ť 2 [ARG1]Ť 3 [ARG2]Ť ...Ť 9 [ARG9]Ť 10 begining of actual argument value storage heapŤŤ*/ŤŤ#include "fort.h"Ť#include ŤŤfexec(heap) int *heap;Ť { int (*func)(), v[9];Ť func = fload(heap[0]);Ť setargs(heap,&heap[2],v,heap[1]);ŤŤ switch (heap[1])Ť { case 0: (*func)(); break;Ť case 1: (*func)(v[0]); break;Ť case 2: (*func)(v[0],v[1]); break;Ť case 3: (*func)(v[0],v[1],v[2]); break;Ť case 4: (*func)(v[0],v[1],v[2],v[3]); break;Ť case 5: (*func)(v[0],v[1],v[2],v[3],v[4]); break;Ť case 6: (*func)(v[0],v[1],v[2],v[3],v[4],v[5]); break;Ť case 7: (*func)(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); break;Ť case 8: (*func)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); break;Ť case 9: (*func)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); break;Ť default: break;}Ť heap[0] = 0;}ŤŤŤsetargs(absbase,reloffsets,v,n) int *absbase, *reloffsets, **v,n;Ť { int j;Ť for (j = 0; Ť j. No specific prompt isŤ;;; provided to the user.Ť(defun get-command ()Ť "Calls appropriate line editor functions for commands input by the user."Ť (let ((command (read)))Ť‰(selectq commandŤ‰ (q (format t "~%Editing session ended."))Ť‰ (i (insert) (display) (get-command))Ť‰ (a (begin-line) (display)(get-command))Ť‰ (e (end-line) (display) (get-command))Ť‰ (f (forward) (display) (get-command))Ť‰ (b (back) (display) (get-command))Ť‰ (d (delete-it) (display) (get-command))Ť‰ (otherwise (format t "Not a legal command. Try again.")Ť‰‰ (get-command)))))ŤŤŤŤ;;; Function INSERT puts the user into insert mode.Ť;;; Insertion before the cursor is accomplished by pushing a new elementŤ;;; onto *buffer1*.Ť(defun insert ()Ť "Inserts an atom into a line of text."Ť (array-push-extend *buffer1* (read)))Ť ŤŤ;;; Function BEGIN-LINE moves the cursor to the beginning of the line byŤ;;; transfering the active contents of *buffer1* into *buffer2*. Ť(defun begin-line ()Ť "Move cursor to the beginning of the current line."Ť (cond ((zerop (fill-pointer *buffer1*))) ; already at beginningŤ‰(t (loop for i from 0 to (sub1 (fill-pointer *buffer1*))Ť‰‰‰‰ do (transfer *buffer1* *buffer2*)))))Ť ŤŤ;;; Function END-LINE moves the cursor to the end of the line by Ť;;; transfering the active contents of *buffer2* into *buffer1*.Ť(defun end-line ()Ť "Move cursor to the end of the current line."Ť (cond ((zerop (fill-pointer *buffer2*))) ; already at endŤ‰(t (loop for i from (sub1 (fill-pointer *buffer2*)) downto 0Ť‰‰‰‰ do (transfer *buffer2* *buffer1*)))))ŤŤŤ;;; Function FORWARD moves the cursor forward one position by transferringŤ;;; the top element of *buffer2* into *buffer1*.Ť;;; Note the alternative test for whether already at the end of the line,Ť;;; as compared to the previous function.Ť(defun forward ()Ť "Moves the cursor forward one position."Ť (cond ((null (aref *buffer2* 0)) (beep-on-terminal)) Ť‰ (t (transfer *buffer2* *buffer1*)))) Ť ŤŤŤ;;; Function BACK moves the cursor back one position by transferring Ť;;; the top element of *buffer1* into *buffer2*.Ť(defun back ()Ť "Moves the cursor back one position."Ť (cond ((zerop (fill-pointer *buffer1*)) (beep-on-terminal)) Ť‰ (t (transfer *buffer1* *buffer2*))))ŤŤŤ;;; Function DELETE removes the item before the cursor by popping offŤ;; *buffer1*. There is no provision here for yanking back this deletion.Ť(defun delete-it ()Ť (cond ((not (null (aref *buffer1* 0))) ; nothing to deleteŤ‰ (array-pop *buffer1*))Ť‰(t (beep-on-terminal))))ŤŤŤLMFL(:BYTE-SIZE 16 :LENGTH-IN-BLOCKS 4 :LENGTH-IN-BYTES 2048 :AUTHOR "ESMITH" :CREATION-DATE 2686576591 :QFASLP NIL :LENGTH 2048 :DIRECTORY "LISP2-CIRCULATION" :NAME "LISPM" :TYPE "INIT" :VERSION 2) hưs2€D€ p€,€¬COMPILE-DATAD€ě€ESMITHěTest Lambda C€†€! §ĺF€fF€;D€p€,COMPILER,‚NEW-DESTINATIONSp€ě€GLOBALl€T€p€B€ ¬€SITEp€B€ ¬€LMI€p€B€ ¬QFASL-SOURCE-FILE-UNIQUE-ID€1€D€p€l€FSě‚MAKE-FASLOAD-PATHNAME€D€p€B€+ě€QUOTE€¬€LAMBD€B€:¬€DSK€D€B€:l‚LISP2-CIRCULATION€D€B€:ě€LISPM€D€B€:¬€LISPD€B€:F€p€B€ ¬€BASEF€ p€B€ lPATCH-FILEp€B€ l€T€p€B€ ě€FONTS€D€p€B€ ě€MEDFNTp€B€ ě€HL12I€p€B€ ,PACKAGE€p€B€ ¬€USER1€D€€AND€D€C€<€D€p€l€SIl‚GET-SYSTEM-VERSIONF€_D€Ă€PROGN€D€Ă‚SET-SYNTAX-MACRO-CHAR€F€D€FUNCTIOND€Ă€LAMBDAD€Ă€SPLICEĂ€STREAM€&AUXD€€CHARD€€SENDB€jD€B€:p€B€ ¬€TYI€D€SELECTQ€B€lD€D€ F€0F€1F€2F€3F€4F€5F€6F€7F€8F€9F€*D€Ă€VALUESB€i€NIL€B€-D€p€B€ lOTHERWISE€D€B€mB€jD€B€:p€B€ ě€UNTYI€B€lD€B€D€Ă€INTERND€Ă€STRINGF€B€‚B€‚1€D€€CONSD€B€:D€PKG-GOTOLOGOUT-LIST€N€źB€ť1€D€Ă€MAPCARD€B€:CLOGIN-EVALD€B€:D€D€€SETQpŔ¬€ZWEIl…*CHECK-UNBALANCED-PARENTHESES-WHEN-SAVING*B€-D€B€ŁpŔB€¤ě‚*INITIAL-MINOR-MODES*€D€B€:D€pŔB€¤ěATOM-WORD-MODED€B€ŁpŔB€¤ěLISP-MODE-HOOKD€B€:pŔB€¤l„ELECTRIC-SHIFT-LOCK-IF-APPROPRIATED€ B€Ł€BASEF€ Ă€IBASE€F€ B€µF€ B€·F€ *NOPOINTB€-D€B€ŁpŔB€¤¬‚*FILE-VERSIONS-KEPT*F€pŔB€¤ě‚*KILL-INTERVAL-SMARTS*B€-D€€DEFFC€PPD€B€:‚GRIND-TOP-LEVEL€D€Ă€DEFUN€C€G€D€C€X€D€B€ĹB€ĘD€B€ČpŔl€TVl‚MAKE-IDLE-MESSAGE€D€MINUTES€D€€CONDD€D€B€]B€ŃF€<D€Ă€FORMATB€‚¬Goofing off for ~D minute~:PB€ŃD€B€-D€€LET€D€D€Ă€HOURS€D€C€/€B€ŃF€<D€C€IFD€C€>€B€ŰF€ D€B€ŁB€ŰD€C€-€B€ŰF€ D€B€ÖB€‚l…User absent or asleep for ~d hr ~d min~:P€B€ŰD€B€ĺB€ŃD€C€*€F€<B€Ű1€D€FUNCALL€pŔB€ÎěWHO-LINE-DOCUMENTATION-WINDOW€D€B€:p€B€ ¬SET-FONT-MAPD€B€:D€Ă€HL10B€1€D€B€řTERMINAL-IO€D€B€:B€üD€B€:D€p€ě€FONTS€,CPTFONT€p€B€ě€MEDFNBp€B€ě€BIGFNTp€B€¬€5X5€1€D€B€řB€D€B€:p€B€ ,‚SET-CURRENT-FONTD€B€:B€1€D€B€šD€B€:€ZWEI1€D€Ă€DEFCOM‚COM-INDENT-SEXP€,śIndent the following s-expression. Each line that starts withinŤ the s-expression is indented for Lisp, assuming that the lineŤ the current set point is on is NOT adjusted. This command willŤ indent the first line as well.€B€‚D€‚COM-INDENT-FOR-LISP€D€B€ÚD€D€€BP1€D€C€ORD€BEG-LINED€Ă€POINT€F€D€€BARFD€€BP2€D€B€"D€FORWARD-SEXPD€B€$D€B€(D€B€\D€€BP- HOURS 12.) (SETQ HOURS (- HOURS 12.)))Ť (FORMAT NIL "User absent or asleep for ~d hr ~d min~:P"Ť hours (- minutes (* 60. hours)))))))Ť))ŤŤ;;; 1Make WHO-LINE DOC window readable*Ť(SEND TV:WHO-LINE-DOCUMENTATION-WINDOW ':SET-FONT-MAP '(HL10B))ŤŤ;1;; set up default* 1font map, for what it is worth*Ť(SEND TERMINAL-IO ':SET-FONT-MAPŤ '(FONTS:CPTFONT FONTS:MEDFNB FONTS:BIGFNT FONTS:5X5))Ť(SEND TERMINAL-IO ':SET-CURRENT-FONT 'FONTS:CPTFONT)ŤŤ;1; Zwei (ie, ZMACS*) 1customizations.*Ť(PKG-GOTO 'ZWEI)ŤŤ(PROGN 'COMPILE ;1;; a typical ZMACS customization*ŤŤ(DEFCOM COM-INDENT-SEXPŤ"Indent the following s-expression. Each line that starts withinŤ the s-expression is indented for Lisp, assuming that the lineŤ the current set point is on is NOT adjusted. This command willŤ indent the first line as well."Ť ()Ť (COM-INDENT-FOR-LISP)Ť (LET ((BP1 (OR (BEG-LINE (POINT) 1) (BARF)))Ť‰(BP2 (OR (FORWARD-SEXP (POINT)) (BARF))))Ť (AND (BP-< BP1 BP2)Ť‰ (WITH-UNDO-SAVE ("Indent sexp" BP1 BP2 T)Ť‰‰‰ (INDENT-INTERVAL-FOR-LISP BP1 BP2 T))))Ť DIS-TEXT)ŤŤ) 1;;; end of (PROGN 'COMPILE ...* 1formŤŤ;;;Set up some ZMacs commands for me* (1most of these are Control-Shift or Meta-Shift).*Ť(LOGIN-EVALŤ (set-comtab-return-undo *standard-comtab*Ť‰‰ '(#\ctrl-altmode com-expand-onlyŤ‰‰ #\super-ctrl-c com-microcompile-defunŤ‰ ‰ #\Hyper-Ctrl-D com-quick-disassembleŤ‰‰ #\ctrl-top-e com-evaluate-defunŤ‰‰ #\Super-altmode com-make-word-abbrevŤŤ 1;;; Set up hand keys to work like arrow keys*Ť‰‰‰ #\hand-up com-up-real-line Ť‰‰‰ #\hand-down com-down-real-line Ť‰‰‰ #\hand-left com-backwardŤ‰‰‰ #\hand-right com-forwardŤŤ‰‰‰ 1;;; Make Roman keys do useful things*Ť‰‰‰ #\roman-i com-backward-paragraphŤ‰‰‰ #\roman-ii com-forward-paragraphŤ‰‰‰ #\roman-iii com-beginning-of-lineŤ‰‰‰ #\roman-iv com-end-of-lineŤŤ‰‰‰ 1;;; Make delete do rubouts*Ť‰‰‰ #\delete com-ruboutŤ‰ Ť 1;;; add various EVAL, COMPILE and MICROCOMPILE options*Ť‰‰ #\Control-//‰ com-Evaluate-RegionŤ‰‰‰ #\Meta-//‰ com-Compile-RegionŤ‰‰‰ #\Control-Meta-// com-Microcompile-RegionŤ‰‰‰ #\Control-/`‰ com-Evaluate-BufferŤ‰‰‰ #\Meta-/`‰ com-Compile-BufferŤ‰‰‰ #\Control-Meta-/` com-Microcompile-BufferŤ‰‰‰ #\Control-{‰ com-Evaluate-Buffer-Changed-SectionsŤ‰‰‰ #\Meta-{‰ com-Compile-Buffer-Changed-SectionsŤ‰‰‰ #\Control-Meta-{ com-Microcompile-Buffer-Changed-SectionsŤ‰‰‰ #\Control-}‰ com-Evaluate-Changed-SectionsŤ‰‰‰ #\Meta-}‰ com-Compile-Changed-SectionsŤ‰‰‰ #\Control-Meta-} com-Microcompile-Changed-SectionsŤ‰‰‰ #\Control-/'‰ com-Evaluate-Mini-Buffer)))Ť‰ Ť(LOGIN-EVALŤ (setq Lisp-Mode-HookŤ‰ #'(lambda ()Ť‰ (turn-on-mode 'Electric-Shift-Lock-Mode)Ť‰ (turn-on-mode 'Return-Indents-Mode)Ť‰ (turn-on-mode 'Electric-Font-Lock-Mode))))Ť‰ Ť(LOGIN-EVALŤ (setq Text-Mode-HookŤ‰ #'(lambda ()Ť‰ (turn-off-mode 'Electric-Shift-Lock-Mode)Ť‰ (turn-on-mode 'Any-Bracket-Mode))))ŤŤ1;;; Leave Lisp Listener in a reasonable context*Ť(PKG-GOTO 'USER)ŤŤ;1;; LOGIN-EVAL this last, so that when logging out, it will be done first.*Ť(LOGIN-EVAL '(ZWEI:SAVE-ALL-FILES))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 4 :LENGTH-IN-BYTES 3404 :AUTHOR "SAM" :CREATION-DATE 2720492885 :QFASLP NIL :LENGTH 3404 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "LIST-PATTERNS" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;LIST PATTERNSŤ;;;Ť;;; LIST PATTERNS "isa" pattern definition, as described in theŤ;;; PATTERN-PROCESSING module. It therefore not only PROVIDEs aŤ;;; LIST-PATTERNS module but also counts as -- and therefore PROVIDEs -- aŤ;;; PATTERN-DEFINITION module.ŤŤ(provide 'list-patterns)‰‰‰;LIST-PATTERNS "isa"Ť(provide 'pattern-definition)‰‰‰; PATTERN-DEFINITION.ŤŤŤ;;;;QUASI-VARIABLES AND VARIABLESŤŤ(defmacro quasi-variable (variable-name)Ť "Given a variable-name string, return a corresponding quasi-variable."Ť `(intern (concatenate 'string "?" ,variable-name)))ŤŤ(defun quasi-variable-p (x)Ť "Is this a quasi-variable?"Ť (and (symbolp x) (char= (char (symbol-name x) 0) #\?)))ŤŤ(defmacro quasi-variable-name (quasi-variable)Ť "Given a quasi-variable, return its name as a string."Ť `(subseq (symbol-name ,quasi-variable) 1))ŤŤŤ(defmacro make-variable (variable-name &optional plist-contents)Ť "Make a pattern variable, given a variable-name string and optionally theŤ contents of a property-list."Ť `(list* #\? ,variable-name (copy-list ,plist-contents)))ŤŤ(defun variable-p (x)Ť "Is this a pattern variable?"Ť (and (consp x) (eql (first x) #\?)))ŤŤ(defmacro variable-name (variable)Ť "Given a pattern variable, return its name as a string."Ť `(second ,variable))ŤŚŤ(defmacro variable-plist (variable)Ť "Given a pattern variable, return its plist contents."Ť `(nthcdr 2 ,variable))ŤŤ(defmacro get-from-variable (variable key &rest other-args-to-getf)Ť "Return the value of pattern variable VARIABLE's KEY property. ThisŤ function is SETF-able."Ť `(getf (variable-plist ,variable) ,key ,@other-args-to-getf))ŤŤŤ(defun make-variable-for (quasi-variable)Ť "Given a quasi-variable, make a corresponding pattern variable."Ť (make-variable (quasi-variable-name quasi-variable)))ŤŤ(defun copy-variable (variable &optional copy-plist-p)Ť "Make a copy of a pattern variable, the copy optionally inheriting a copyŤ of the variable's property-list."Ť (make-variable (variable-name variable)Ť‰‰ (if copy-plist-p (variable-plist variable))))ŤŤ(defun quasi-variable-for (variable)Ť "Given a pattern variable, return a corresponding quasi-variable."Ť (quasi-variable (variable-name variable)))ŤŤŤŤ;;;;CONSTANTSŤŤ(defmacro constant-p (pattern) `(atom ,pattern))ŤŤŤŤ;;;;COMPOSITESŤŤ(defun atomic-p (pattern) (or (atom pattern) (eql (first pattern) #\?)))ŤŤ(defmacro composite-p (pattern) `(not (atomic-p ,pattern)))ŤŤ(defmacro make-composite (next-component rest-of-components)Ť `(cons ,next-component ,rest-of-components))ŤŤ(defmacro next-component (composite-pattern) `(car ,composite-pattern))Ť(defmacro rest-of-components (composite-pattern) `(cdr ,composite-pattern))ŤŚŤ;;;;MATCHING PREDICATESŤŤ(defmacro match-constant-p (constant pattern)Ť "Does CONSTANT match PATTERN? This is a symmetrical test of equality."Ť `(eql ,constant ,pattern))ŤŤ;;; Sacrifice some efficiency to allow other modules to convenientlyŤ;;; supersede this definition.ŤŤ;(defmacro match-variable-p (variable pattern)Ť; (declare (ignore variable pattern))Ť; `t)ŤŤ(defun match-variable-p (variable pattern)Ť (declare (ignore variable pattern))Ť t)ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 43 :LENGTH-IN-BYTES 43532 :AUTHOR "wilde" :CREATION-DATE 2694625097 :QFASLP NIL :LENGTH 43532 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "ORG" :TYPE "LISP" :VERSION 11) ;-*- Mode:LISP; Package:(ORG :USE (USER GLOBAL SYSTEM)); Fonts:CPTFONT; Base:8 -*-Ť Ť;; Copyright LISP Machine, Inc. 1984Ť;; See filename "Copyright.text" forŤ;; licensing and release information.Ť Ť;;; ORG: Organization Chart ProgramŤŤ;;; REVISION HISTORYŤ;;;Ť;;; E. Smith and L. Wilde ‰2/85‰ Revise to work with Release 2.0Ť;;; S. Strassman‰‰7/84‰ Added additional featuresŤ;;; J. Hendler‰‰‰6/84‰ Modify nodes to use "FLAVORS" object class systemŤ;;; L. Hawkinson‰‰Unknown‰ Original VersionŤŤ;------------------------------------------------------------------------------Ť; To use this code:Ť;Ť; Just load this file up and type SYSTEM-O. Ť;Ť;------------------------------------------------------------------------------Ť; Set up our global variables.Ť;Ť; Note the convention of beginning each one with an asterisk.Ť; Also, every one has a documentation string.Ť;ŤŤ(defvar *chart-frame :unboundŤ "frame for org process")ŤŤ(defvar *chart-pane :unboundŤ "org chart pane in org chart frame")ŤŤ(defvar *command-pane :unboundŤ "command pane in org chart frame")ŤŤ(defvar *prompt-pane :unboundŤ "prompt pane in org chart frame")ŤŤ(defvar *default-attributesŤ‰'(("Name" "anonymous")Ť‰ ("Title" *needs-filling-in)Ť‰ ("Location" *needs-filling-in))Ť "The default list of attributes a node could have.")ŤŤ(defconst *needs-filling-in "*****"Ť "value for descriptor not (yet) filled in")ŤŤ(defvar *closed-width 15.Ť "The width of a closed node")ŤŤ(defvar *closed-height 8.Ť "The height of a closed node")ŤŤ(defconst *alu tv:alu-ior "TV algorithm for drawing characters")ŤŤ(defconst *scroll-amount 100. "Number of pixels to scroll on the scroll command")ŤŤ(defvar *file (fs:merge-pathname-defaults "foo.chart")Ť "The filename to store the current chart under.")ŤŤ(defvar *default-h-separation 10)Ť(defvar *default-v-separation 10)ŤŤ;------------------------------------------------------------------------------Ť; NodesŤŤ; A node has the following instance variables, which keep track of the stateŤ; of that node:Ť;Ť; opened?: A closed node exists, but is invisible. An opened node is visible.Ť; attributes: A list of sublists (i.e. an "alist"). Each sublist is a list ofŤ; two strings: a slot (eg: "Name"), and its value (eg: "Melvin").Ť; A special value is the variable *NEEDS-FILLING-IN.Ť; justification One of three keywords: :CENTER, :LEFT, or :RIGHT.Ť; extra-width: How much whitespace to put inside the box around the textŤ; (horizontally)Ť; vertical-separation: How much whitespace to put beneath this node and its inferiors.Ť; horizontal-separation: How much whitespace to put between each inferior.Ť; above: The node above this oneŤ; below: A list of the nodes below this oneŤ; pane: The window this node draws itself onŤ; height: The height of this node's box in pixelsŤ; width: The width of this node's box in pixelsŤ; sub-tree-height: The height of the sub-tree including this node in pixelsŤ; sub-tree-width: The width of the sub-tree including this node in pixelsŤ; left: The left edge of this node in screen coordinatesŤ; top: The top edge of this node in screen coordinatesŤŤ(defflavor nodeŤ ((opened? t)‰‰‰‰; are you visible?Ť‰ (attributes *default-attributes)‰; an alist of print valuesŤ‰ (justification ':center)‰‰; how to print the valuesŤ‰ (extra-width 10.)‰‰‰; extra margin in pixelsŤ‰ (vertical-separation *default-v-separation)Ť‰ (horizontal-separation *default-v-separation)Ť‰ (above nil)‰‰‰‰; the node aboveŤ‰ (below nil)‰‰‰‰; the nodes belowŤ‰ pane‰‰‰‰‰; the window to draw-self onŤ‰ height‰‰‰‰‰; in pixelsŤ‰ width‰‰‰‰‰; in pixelsŤ‰ sub-tree-width‰‰‰‰; visible sub-treeŤ‰ sub-tree-height‰‰‰; visible sub-treeŤ‰ left‰‰‰‰‰; x coordinate of left edgeŤ‰ top)‰‰‰‰‰; y coordinate of top edgeŤ‰()Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤ(defmethod (node :after :init) (&rest ignore)Ť (send self ':compute-dimensions))ŤŤ;------------------------------------------------------------------------------Ť;Ť; Node methods I: Ť; How to draw nodes; including geometry computationsŤ;ŤŤ; This computes the height and width of a node, based on what strings goŤ; inside it. Note that this is independent of where on the screen the node is.Ť;Ť(defmethod (node :compute-dimensions) (&rest ignore)Ť (cond ((not opened?)Ť‰ (setq width *closed-width)Ť‰ (setq height *closed-height)Ť‰ (setq sub-tree-width *closed-width)Ť‰ (setq sub-tree-height *closed-height))Ť‰(t (setq widthŤ‰‰ (+ extra-widthŤ‰‰ (loop for attribute in attributesŤ‰‰‰ if (send self ':ought-to-print-attribute? attribute)Ť‰‰‰ maximize (send pane ':string-length (eval (second attribute))))))Ť‰ (setq heightŤ‰‰ (+ (send pane ':vsp)Ť‰‰ (loop for attribute in attributesŤ‰‰‰ if (send self ':ought-to-print-attribute? attribute)Ť‰‰‰ sum (+ (send pane ':vsp)Ť‰‰‰‰ (tv:font-char-height (send pane ':current-font)))))))))ŤŤŤŤ; This is a recursive procedure. You call it on the topmost nodeŤ; which you're interested in, and all of its underlings will beŤ; called with the same :COMPUTE-TOTAL-DIMENSIONS message. Thus, thisŤ; returns the total width and total height (in pixels) of the sub-treeŤ; beginning with any node. Unopened cells, of course, take up no room.Ť;Ť; First, the node's own height and width is computed.Ť; Then, all the space occupied below is computed (depth-first).Ť; The value returned is a list of the entire width and the entire height.Ť; Note that the width is the maximum of this node's width and Ť; the width of its underlings (max width total-width)Ť; The height is the sum of three things: this node's height, the verticalŤ; separation between layers, and the max of the underlings' heights.ŤŤ; This method makes sure everyone's HEIGHT and WIDTH are up to date.Ť; The next method, :reposition-underlings, makes sure everyone'sŤ; TOP and LEFT are up to date.Ť;Ť(defmethod (node :compute-total-dimensions) (&rest ignore)Ť (send self ':compute-dimensions)Ť (cond ((not opened?) (list width height))Ť‰((null below)Ť‰ (setq sub-tree-width width)Ť‰ (setq sub-tree-height height)Ť‰ (list width height))Ť‰(tŤ‰ (loop for underling in belowŤ‰ for under-dim = (send underling ':compute-total-dimensions)Ť‰ sum (+ horizontal-separationŤ‰‰ (first under-dim)) into under-width Ť‰ maximize (second under-dim) into under-heightŤ‰ finally Ť‰ (returnŤ‰‰ (prognŤ‰‰ (setq sub-tree-width (max width (- under-width horizontal-separation)))Ť‰‰ (setq sub-tree-height (+ height‰; my heightŤ‰‰‰‰‰ vertical-separation‰; height directly under meŤ‰‰‰‰‰ under-height))‰; my underlings' heightŤ‰‰ (list sub-tree-width sub-tree-height)))))))ŤŤŤ; This is also a recursive procedure which makes sure everyone'sŤ; TOP and LEFT are ok. It does this by finding out where its underlingsŤ; are, and then positioning itself on top of them, in the center.Ť; Note that this really has to call :COMPUTE-TOTAL-DIMENSIONS first,Ť; but :COMPUTE-TOTAL-DIMENSIONS doesn't really need to call Ť; :REPOSITION-UNDERLINGS in order to work. For extra credit: Why is this so?Ť;Ť(defmethod (node :reposition-underlings) ()Ť (if (not opened?) nilŤ (let* ((under-width‰‰‰‰; the width of all my underlingsŤ‰ (- (loop for underling in belowŤ‰‰‰summing (+ (send underling ':sub-tree-width)Ť‰‰‰‰ horizontal-separation))Ť‰‰ horizontal-separation))Ť‰ (under-left (- (+ left (* .5 width))‰; middle of this nodeŤ‰‰‰ (* .5 under-width))))‰; left edge of sub-treeŤ‰(loop for underling in belowŤ‰ for dx first under-left then (+ dx under-sub-tree-widthŤ‰‰‰‰‰ horizontal-separation)Ť‰ for under-sub-tree-width = (send underling ':sub-tree-width)Ť‰ do (send underling ':set-top (+ top height vertical-separation))Ť‰ (send underling ':set-leftŤ‰‰ (- (+ dx (* .5 under-sub-tree-width))‰; center of sub-treeŤ‰‰ (* .5 (send underling ':width))))‰; offset of underling's widthŤ‰ (send underling ':reposition-underlings)))))ŤŤ; Drawing stuff.Ť;Ť; This is the procedure you call on the top node to get the whole treeŤ; drawn. It draws itself, and then each of its underlings (which, of courseŤ; head subtrees themselves) get drawn the same way. If you have the special Ť; case that a node is "closed", you give it to the special :DRAW-CLOSED method.Ť;ŤŤ(defmethod (node :draw-sub-tree) ()Ť (if (not opened?) (send self ':draw-closed)Ť (send self ':draw)Ť (cond ((> (length below) 1)Ť‰ (send self ':draw-under-line)Ť‰ (loop for underling in belowŤ‰‰ do (send self ':draw-line-to underling)Ť‰‰ do (send underling ':draw-sub-tree)))Ť‰ ((= (length below) 1)Ť‰ (send pane ':draw-line (fix (+ left (* .5 width)))Ť‰‰ (fix (+ top height))Ť‰‰‰‰ (fix (+ left (* .5 width)))Ť‰‰‰‰ (fix (+ top height vertical-separation -1)))Ť‰ (send (car below) ':draw-sub-tree)))))ŤŤ(defmethod (node :draw-under-line) ()Ť (let* ((left-node (first below))Ť‰ (right-node (car (last below)))Ť‰ (top-x (fix (+ left (* .5 width))))Ť‰ (top-y (fix (+ top height)))Ť‰ (left-x (fix (+ (send left-node ':left)Ť‰‰‰ (* .5 (send left-node ':width)))))Ť‰ (right-x (fix (+ (send right-node ':left)Ť‰‰‰ (* .5 (send right-node ':width)))))Ť‰ (bottom-y (fix (+ top-y (* .5 vertical-separation)))))Ť (send pane ':draw-line top-x top-y top-x (1- bottom-y) *alu)Ť (send pane ':draw-line left-x bottom-y right-x bottom-y *alu)))ŤŤ; This draws the line from superior to underling.Ť; The FIXR operations convert any kind of number into an integer.Ť; FIX does this by truncation, FIXR rounds off the argument. Ť; This is because graphics commands can't handle floating pointŤ; for screen coordinates.Ť;Ť(defmethod (node :draw-line-to) (underling)Ť (let* ((top-x (fix (+ (send underling ':left)Ť‰‰‰(* .5 (send underling ':width)))))Ť‰ (top-y (fix (+ top height (* .5 vertical-separation))))Ť‰ (bottom-y (fix (- (send underling ':top) 1))))Ť (send pane ':draw-line top-x top-y top-x bottom-y *alu)))ŤŤŤ; This is called by :DRAW-SUB-TREE. It draws just the box and contents forŤ; itself, but it doesn't draw connecting lines or any of its underlings.Ť; If an attribute shouldn't be printed, it doesn't get printed.Ť; Notice the abstractions here. Such decisions as "How should the edgesŤ; be drawn?" "Should this attribute be printed?" "How should it look?"Ť; are not decided here. Why did I write these as separate functions?Ť;Ť(defmethod (node :draw) (&aux (char-height (tv:font-char-height (send pane ':current-font))))Ť (send self ':draw-edges)Ť (loop for attribute in attributesŤ‰for print? = (send self ':ought-to-print-attribute? attribute)Ť‰for y first (+ top (send pane ':vsp))Ť‰ then (if print? (+ y char-height (send pane ':vsp))Ť‰‰ y)Ť‰do (if print?Ť‰ (send self ':print-attribute attribute y))))ŤŤ; The box around the nodeŤ;Ť(defmethod (node :draw-edges) ()Ť (send pane ':draw-lines *aluŤ‰(fix left)(fix top)Ť‰(fix (+ left width)) (fix top)Ť‰(fix (+ left width)) (fix (+ top height))Ť‰(fix left)(fix (+ top height))Ť‰(fix left)(fix top)))ŤŤ; This method defines how closed boxes draw themselves. You drawŤ; only its edges (which were set to be really small in :COMPUTE-DIMENSIONS Ť; because this node is closed, and then color it gray.ŤŤ(defmethod (node :draw-closed) ()Ť (send self ':draw-edges)Ť (send pane ':bitblt *alu (fix (1- width)) (fix (1- height))Ť‰tv:33%-gray 0 0 (fix (1+ left)) (fix (1+ top))))ŤŤŤ; Notice the way this implementation allows you to use "*****"Ť; to represent the notion of needing filling-in, yet you are notŤ; prohibited from including your Martian employees ("*****" isŤ; a common Martian family name, you know) on this chart.Ť; A professional programmer never has "magic" values that mightŤ; cause an innnocent user some grief some day.Ť;Ť(defmethod (node :ought-to-print-attribute?) (attribute)Ť (and (cdr attribute)Ť (not (eq (second attribute) '*needs-filling-in))))ŤŤŤ; Notice the idiom (* .5 foo). This is used to figure out halfŤ; of a region, so things get centered nicely.Ť;Ť(defmethod (node :print-attribute) (attribute y)Ť (let* ((string (eval (second attribute)))Ť‰ (free-space (- width (send pane ':string-length string))))Ť (selectq justificationŤ (:center (label pane (+ left (* .5 free-space)) y string))Ť (:left (label pane (+ (* .5 extra-width) left) y string))Ť (:right (label pane (+ left free-space (* -.5 extra-width)) y string)))))Ť‰‰ ŤŤ; The following is a short-hand notation for the corrected :STRING-OUT message.Ť;Ť(defun label (window left top string)Ť (if (or (< top 0) (< left 0)) nilŤ (send window ':set-cursorpos (fix left) (correct window top))Ť (send window ':string-out string)))ŤŤ(defun correct (window top)Ť (fix (+ topŤ‰ (tv:font-baseline (send window ':current-font))Ť‰ (- (tv:font-baseline (aref (send window ':font-map)Ť‰‰‰‰‰(send window ':largest-font)))))))Ť Ť; The string-out message is very useful, since it's a very explicitŤ; way of getting typout on a screen. Some other favorite ways of printingŤ; include (this is by no means an exhaustive list):Ť;Ť; (send ':draw-char )Ť; (format . )Ť; (print )Ť; (princ )Ť; (prin1 )Ť; (send ':tyo )Ť Ť;------------------------------------------------------------------------------Ť;Ť; Node methods II:Ť; Maintaining the contentsŤ;Ť; There's several ways you may want to edit the attributes, andŤ; rather than bother the user with one big menu, this is an exerciseŤ; in menu hacking. Ť;Ť; In creating a menu, you must specify everything the computer cannotŤ; figure out for itself. For example, things you must specify include:Ť;Ť; What the items to choose from are; what to do when you select one of them,Ť; what to do when you DON'T select one of them, what the mouse documentationŤ; who-line should say when you're pointing at the item, etc.Ť;Ť; Every menu has an which, for each item, specifiesŤ; just what kind of actions and items you have. For more informationŤ; on the different kinds of menus, consult the Window System Manual.Ť;Ť(defmethod (node :edit) ()Ť‰ (send pane ':set-current-node self)Ť‰ (tv:menu-choose '(("Modify Contents" :eval (send (send *chart-paneŤ‰‰‰‰‰‰‰‰':current-node)Ť‰‰‰‰‰‰‰ ':fill-in-self)Ť‰‰‰ :documentation "Modify the contents of this node")Ť‰‰‰ ("Select Attributes" :eval (send (send *chart-paneŤ‰‰‰‰‰‰‰‰ ':current-node)Ť‰‰‰‰‰‰‰ ':select-attributes)Ť‰‰‰ :documentation "Remove one or more attributes of this node")Ť‰‰‰ ("Change Geometry" :eval (send (send *chart-paneŤ‰‰‰‰‰‰‰‰':current-node)Ť‰‰‰‰‰‰‰ ':change-geometry)Ť‰‰‰ :documentation "Change the display features of this node")))Ť‰ (send pane ':refresh))ŤŤ; Choose-variable-values only modifies the values of variables.Ť; I wanted to modify the elements of a list, so I needed to GENSYM some newŤ; variables. GENSYM creates a symbol that is guaranteed brand-new,Ť; and I generate as many as I need to hold all the attributes. Ť; Then I call up a CHOOSE-VARIABLE-VALUES on these variables, andŤ; put everything back when I'm finished.Ť;Ť(defmethod (node :fill-in-self) ()Ť (let ((vars (loop for attribute in attributesŤ‰‰ for var = (gensym 'attribute)Ť‰‰ do (setf (plist var)Ť‰‰‰ (append (plist var)Ť‰‰‰‰ '(si:documentation-property (("variable"))Ť‰‰‰‰ special t)))Ť‰‰ (set var (second attribute))Ť‰‰ collect var))Ť‰(base 10.)Ť‰(ibase 10.))Ť (tv:choose-variable-valuesŤ (loop for var in varsŤ‰ for attribute in attributesŤ‰ collecting (list varŤ‰‰‰ (first attribute)Ť‰‰‰ ':string))Ť ':label "Fill in as appropriate:"Ť ':near-mode '(:mouse)Ť ':margin-choices '("Mouse here when done"))Ť (setq attributesŤ‰ (loop for var in varsŤ‰ for attribute in attributesŤ‰ collecting (list (first attribute) (eval var))))))ŤŤŤ; Multiple-choose menus provide columns and rows of boxes.Ť; Each box can be on or off, and turning it on or off may cause other boxesŤ; to turn on or off. Consult the Window System Manual for more info.Ť;Ť; The items are labeled with strings like "Name: Mary" if a value is found,Ť; and a string like "Name" if not found. Notice the use of back-quoted listsŤ; and commas in order to control creation of the item list.Ť;Ť(defmethod (node :select-attributes) ()Ť (let ((selectionsŤ‰ (tv:multiple-chooseŤ‰ "This node's attributes"Ť‰ (loop for default-attribute in *default-attributesŤ‰‰ for found = (assoc (first default-attribute) attributes)Ť‰‰ collectingŤ‰‰ (if foundŤ‰‰ (copytree (list found (string-append (first found) ": " (second found))Ť‰‰‰ '((:keep t t nil nil) (:remove nil t nil nil))))Ť‰‰ ; if not foundŤ‰‰ (copytree (list default-attribute (first default-attribute)Ť‰‰‰ '((:keep nil t nil nil) (:remove t t nil nil))))))Ť‰ (copytree '((:keep " Keep " nil t t nil)Ť‰ (:remove " Remove " nil t t nil))))))Ť (if selectionsŤ‰(setq attributes (loop for item in selectionsŤ‰‰‰ if (eq (second item) ':keep)Ť‰‰‰ collect (first item))))))ŤŤ; This allow a user to modify the appearance of a box, or the separationŤ; of a box's underlings. This is in a different menu from the other two, Ť; because the nature of the information is rather different.Ť;Ť(defmethod (node :change-geometry) ()Ť (let* ((base 10.)Ť‰ (ibase 10.)Ť‰ (properties '(justification extra-widthŤ‰‰ vertical-separation horizontal-separation))Ť‰ (vars (loop for property in propertiesŤ‰‰ for var = (gensym 'prop)Ť‰‰ do (setf (plist property)Ť‰‰‰ (append (plist property)Ť‰‰‰‰ '(si:documentation-property (("variable"))Ť‰‰‰‰ special t)))Ť‰‰ (setf (plist var)Ť‰‰‰ (append (plist var)Ť‰‰‰‰ '(si:documentation-property (("variable"))Ť‰‰‰‰ special t)))Ť‰‰ (set var (send self ':eval-inside-yourself property))Ť‰‰ collect var)))Ť (tv:choose-variable-valuesŤ (loop for var in varsŤ‰ for doc in '(("Justification" :choose (:center :left :right))Ť‰‰‰ ("Extra box width (10 is good)" :number)Ť‰‰‰ ("Vertical distance to underlings" :number)Ť‰‰‰ ("Separation between underlings" :number))Ť‰ collecting (cons var doc))Ť ':label "All numbers are in pixels:"Ť ':near-mode '(:mouse)Ť ':margin-choices '("Mouse here when done"))Ť (loop for property in propertiesŤ‰ for var in varsŤ‰ do (send self ':eval-inside-yourself `(setq ,property ,var)))))ŤŤ;------------------------------------------------------------------------------Ť;Ť; Node methods III:Ť; Adding and deleting nodesŤŤŤ; Yes Virginia, FIND-POSITION-IN-LIST, FIRSTN, and NTHCDR are lisp primitives!Ť; Aren't you glad some nut wrote them for us?Ť;Ť(defmethod (node :left-siblings-of) (node)Ť (if (not (memq node below)) nilŤ (firstn (find-position-in-list node below) below)))ŤŤ(defmethod (node :right-siblings-of) (node)Ť (if (not (memq node below)) nilŤ (cdr (nthcdr (find-position-in-list node below) below))))ŤŤ; Create a new underlingŤ;Ť(defmethod (node :add-below) ()Ť (let ((new (make-instance 'node ':pane paneŤ‰‰‰ ':horizontal-separation *default-h-separationŤ‰‰‰ ':vertical-separation *default-v-separation)))Ť (setq below (append below (list new)))Ť (send new ':set-above self)Ť (send new ':fill-in-self)Ť (send pane ':refresh)Ť (send pane ':set-current-node new)))ŤŤ; Create a new superior. Don't forget to inform the superior's superiorŤ; about this, and if you've made a brand-new top-node for the chart, Ť; inform the chart-pane too, while you're at it.Ť;Ť(defmethod (node :add-above) ()Ť (let ((new (make-instance 'node ':pane paneŤ‰‰‰ ':horizontal-separation *default-h-separationŤ‰‰‰ ':vertical-separation *default-v-separation)))Ť (send new ':set-above above)Ť (send new ':set-below (list self))Ť (setq above new)Ť (cond ((eq self (send pane ':top-node))‰; If a new top is createdŤ‰ (send pane ':set-top-node new)Ť‰ (send new ':fill-in-self)Ť‰ (send pane ':go-to-top))Ť‰ ((send new ':above)‰‰‰; Else we must inform it of a new inferiorŤ‰ (send (send new ':above) ':set-belowŤ‰‰ (append (send (send new ':above) ':left-siblings-of self)Ť‰‰‰ (list new)Ť‰‰‰ (send (send new ':above) ':right-siblings-of self)))Ť‰ (send new ':fill-in-self)Ť‰ (send pane ':refresh)Ť‰ (send pane ':set-current-node new)))))ŤŤ; A new siblingŤ;Ť(defmethod (node :add-right) ()Ť (if (null above)Ť (beep-on-terminal)Ť (let ((new (make-instance 'node ':pane paneŤ‰‰‰ ':horizontal-separation *default-h-separationŤ‰‰‰ ':vertical-separation *default-v-separation)))Ť‰(send new ':set-above above)Ť‰(send above ':set-belowŤ‰ (append (send above ':left-siblings-of self)Ť‰‰ (list self new)Ť‰‰ (send above ':right-siblings-of self)))Ť‰(send new ':fill-in-self)Ť‰(send pane ':refresh)Ť‰(send pane ':set-current-node new))))ŤŤŤ; A new siblingŤ;Ť(defmethod (node :add-left) ()Ť (if (null above)Ť (beep-on-terminal)Ť (let ((new (make-instance 'node ':pane paneŤ‰‰‰ ':horizontal-separation *default-h-separationŤ‰‰‰ ':vertical-separation *default-v-separation)))Ť‰(send new ':set-above above)Ť‰(send above ':set-belowŤ‰ (append (send above ':left-siblings-of self)Ť‰‰ (list new self)Ť‰‰ (send above ':right-siblings-of self)))Ť‰(send new ':fill-in-self)Ť‰(send pane ':refresh)Ť‰(send pane ':set-current-node new))))ŤŤ(defmethod (node :remove-self) ()Ť (cond ((null below)Ť‰ (if (null above) (beep-on-terminal)Ť‰ (send above ':set-below (remq self (send above ':below)))Ť‰ (send pane ':set-current-node above)Ť‰ (send pane ':refresh)))Ť‰((null above)Ť‰ (if (< 1 (length below)) (beep-on-terminal)Ť‰ (send (car below) ':set-above nil)Ť‰ (send pane ':set-top-node (car below))Ť‰ (send pane ':go-to-top)))Ť‰(t (send above ':set-belowŤ‰‰ (append (send above ':left-siblings-of self)Ť‰‰‰ belowŤ‰‰‰ (send above ':right-siblings-of self)))Ť‰ (loop for orphan in belowŤ‰‰ do (send orphan ':set-above above))Ť‰ (send pane ':set-current-node above)Ť‰ (send pane ':refresh))))ŤŤ; This keeps a node, and eliminates all subtreesŤ;Ť(defmethod (node :remove-below) ()Ť (if (null below) (beep-on-terminal)Ť (setq below nil) Ť (send pane ':refresh)))ŤŤ;------------------------------------------------------------------------------Ť; Ť; User queriesŤŤ; This prompts the user on the prompt pane for a yes or no answer.Ť; It cleans up the prompt pane when finished by sending a :REFRESH message.Ť;Ť(defun let-user-confirm (query-string)Ť (let ((answer (fquery () query-string)))Ť (send *prompt-pane ':refresh)Ť answer))ŤŤ; This beeps on (and maybe flashes) the user's terminal. Ť;Ť(defun beep-on-terminal ()Ť (send terminal-io ':beep))ŤŤ;------------------------------------------------------------------------------Ť; The pane with the organization chart Ť;ŤŤ(defflavor chart-paneŤ‰((top-node nil)Ť‰ (current-node)Ť‰ (font 3)Ť‰ (largest-font 4)Ť‰ (smallest-font 0))Ť‰(tv:list-mouse-buttons-mixin tv:truncating-window)Ť (:documentationŤ "ORG Chart pane")Ť (:default-init-plistŤ :font-map '(fonts:5x5 fonts:tr8 fonts:tr10 fonts:tr12 fonts:mets)Ť :save-bits tŤ :blinker-flavor 'tv:box-blinkerŤ :label nil)‰‰‰‰‰; no window labelŤ :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤ(defmethod (chart-pane :after :init) (&rest ignore)Ť (setq top-node (make-instance 'node ':pane selfŤ‰‰‰ ':horizontal-separation *default-h-separationŤ‰‰‰ ':vertical-separation *default-v-separation))Ť (setq current-node top-node)Ť (send current-node ':set-top (* .1 (send self ':height)))Ť (send current-node ':set-leftŤ‰(- (* .5 (send self ':width)) Ť‰ (* .5 (send current-node ':width)))))ŤŤŤ(defmethod (chart-pane :after :refresh) (&rest ignore)Ť (send self ':set-current-font font)Ť (send top-node ':compute-total-dimensions)Ť (send top-node ':reposition-underlings)Ť (send top-node ':draw-sub-tree)‰‰; This actually draws the whole graphŤ (send self ':update-blinker))ŤŤ(defmethod (chart-pane :after :set-current-node) (ignore)Ť (send self ':scroll-if-necessary)Ť (send self ':update-blinker))ŤŤ(defmethod (chart-pane :update-blinker) ()Ť (let ((blinker (car (send self ':blinker-list))))Ť (send blinker ':set-sizeŤ‰ (+ 5 (send current-node ':width))Ť‰ (+ 5 (send current-node ':height)))Ť (send blinker ':set-cursorposŤ‰ (- (send current-node ':left) 2)Ť‰ (- (send current-node ':top) 2))Ť (send blinker ':set-visibility t)))ŤŤ;------------------------------------------------------------------------------Ť;Ť; The command pane's functionsŤ;ŤŤ; File storage stuffŤ;Ť(defmethod (chart-pane :save-as-file) ()Ť (with-open-fileŤ (file (send self ':get-file-name-from-user "Save this graph into which file?") ':write)Ť (format file ";-*- Mode:LISP; Package:(ORG :USE (USER GLOBAL SYSTEM)); Base:10. -*- ~3%")Ť (format file "; This file was generated by the ORG program. It contains the ~%")Ť (format file "; information necessary to reconstruct a chart from scratch. ~%")Ť (format file "; ~%")Ť (format file "; Modify this file only if you really know what you're doing.~%")Ť (format file "; It's much better to run ORG, then load this file, modify it,~%")Ť (format file "; and save out the preferred version.~2%")Ť (format file "; This is the top node:")Ť (dump-world t file (send top-node ':dump-subtree))Ť (format file "~3%; That's all, folks!"))Ť (format t "Done.~%"))ŤŤ(defun dump-world (top-node? stream string-tree)Ť (if (null string-tree) nilŤ (let ((node-string (first string-tree))Ť‰ (symbol (second string-tree))Ť‰ (kids (third string-tree)))Ť‰(format stream "~2%(defconst ~A ~A)" symbol node-string)Ť‰(if (not top-node?) nilŤ‰ (format stream "~2%(send *chart-pane ':set-top-node ~A)" symbol)Ť‰ (format stream "~%(send ~A ':set-pane *chart-pane)" symbol))Ť‰(loop for kid in kidsŤ‰ do (dump-world nil stream kid)Ť‰ do (format stream "~%(send ~A ':greet-new-inferior ~A)"Ť‰‰ symbol (second kid))))))ŤŤ(defmethod (node :greet-new-inferior) (node)Ť (setq below (append below (list node)))Ť (send node ':set-above self))ŤŤŤ(defmethod (node :dump-subtree) ()Ť (let ((nodename (gensym 'node)))Ť (list (send self ':dump-string)Ť‰nodenameŤ‰(loop for kid in belowŤ‰ collect (send kid ':dump-subtree)))))ŤŤŤ(defmethod (node :dump-string) ()Ť (let ((base 10.))Ť (string-appendŤ (format nil "~% (make-instance 'node ~%")Ť (format nil " ':pane *chart-pane ~%")Ť (format nil " ':opened? ~S ~%" opened?)Ť (format nil " ':attributes~%")Ť (format nil " '~S ~%" attributes)Ť (format nil " ':justification ':~S ~%" justification)Ť (format nil " ':extra-width ~S ~%" extra-width)Ť (format nil " ':vertical-separation ~S ~%" vertical-separation)Ť (format nil " ':horizontal-separation ~S)" horizontal-separation))))ŤŤŤ(defmethod (chart-pane :get-file-name-from-user) (prompt-string)Ť (let ((fn (prompt-and-read `(:pathname :defaults ,*file)Ť‰‰‰ "~%~A (default: ~A) " prompt-string *file)))Ť (setq *file (fs:merge-pathname-defaults fn))))ŤŤ(defmethod (chart-pane :restore-from-file) ()Ť (cond ((fquery ()Ť‰ "Are you sure you want to wipe out everything and load a brand-new chart? ")Ť‰ (load (send self ':get-file-name-from-user "File to load"))‰ Ť‰ (send self ':go-to-top)Ť‰ (format t "Done.~%"))))ŤŤ;------------------------------------------------------------------------------Ť;Ť; Font nonsenseŤ;Ť(defmethod (chart-pane :make-bigger) ()Ť (if (equal font largest-font)Ť (beep-on-terminal)Ť (setq font (1+ font))Ť (send self ':set-current-font font))Ť (send self ':refresh))Ť Ť(defmethod (chart-pane :make-smaller) ()Ť (if (equal font smallest-font)Ť (beep-on-terminal)Ť (setq font (1- font))Ť (send self ':set-current-font font))Ť (send self ':refresh))ŤŤ(defmethod (chart-pane :change-parameters) ()Ť (let ((base 10.)Ť‰(ibase 10.))Ť (tv:choose-variable-valuesŤ `((*closed-width "Width of a closed box (15 is good)" :number)Ť‰(*closed-height "Height of a closed box (8 is good)" :number)Ť‰(*default-v-separation "Default space under a node (10 is good)" :number)Ť‰(*default-h-separation "Default space between nodes (10 is good)" :number)Ť‰(*scroll-amount "How big a jump to make when scrolling (100 is good)" :number)Ť‰(*file "The pathname of the current file" :pathname)))))ŤŤ(defmethod (chart-pane :go-to-top) ()Ť (setq current-node top-node)Ť (send current-node ':set-top (* .1 (send self ':height)))Ť (send current-node ':set-leftŤ‰(- (* .5 (send self ':width)) Ť‰ (* .5 (send current-node ':width))))Ť (send self ':refresh))ŤŤ(defmethod (chart-pane :go-up) ()Ť (let ((boss (send current-node ':above)))Ť (if (null boss)Ť‰(beep-on-terminal)Ť‰(send self ':set-current-node boss))))ŤŤ(defmethod (chart-pane :go-down) ()Ť (let ((underlings (send current-node ':below)))Ť (if (or (not (send current-node ':opened?)) (null underlings))Ť‰(beep-on-terminal)Ť‰(send self ':set-current-node (car underlings)))))ŤŤ(defmethod (chart-pane :go-left) ()Ť (let ((boss (send current-node ':above)))Ť (if (null boss)Ť‰(beep-on-terminal)Ť‰(let ((left-kid (car (last (send boss ':left-siblings-of current-node)))))Ť‰ (cond ((null left-kid)Ť‰‰(send self ':go-up))Ť‰ (t‰‰ Ť‰‰(send self ':set-current-node left-kid)))))))ŤŤŤ(defmethod (chart-pane :go-right) ()Ť (let ((boss (send current-node ':above)))Ť (if (null boss)Ť‰(send self ':go-down)Ť‰(let ((right-kid (car (send boss ':right-siblings-of current-node))))Ť‰ (cond ((and (null right-kid) (null (send current-node ':below)))Ť‰‰ (beep-on-terminal))Ť‰‰((null right-kid)Ť‰‰ (send self ':go-down))Ť‰‰(t‰‰ Ť‰‰ (send self ':set-current-node right-kid)))))))ŤŤ(defmethod (chart-pane :far-right) ()Ť (let ((boss (send current-node ':above)))Ť (if (null boss)Ť‰(beep-on-terminal)Ť‰(let ((right-kid (car (last (send boss ':right-siblings-of current-node)))))Ť‰ (cond ((null right-kid)Ť‰‰ (beep-on-terminal))Ť‰‰(t‰‰ Ť‰‰ (send self ':set-current-node right-kid)))))))ŤŤ(defmethod (chart-pane :far-left) ()Ť (let ((boss (send current-node ':above)))Ť (if (null boss)Ť‰(beep-on-terminal)Ť‰(let ((left-kid (car (send boss ':left-siblings-of current-node))))Ť‰ (cond ((null left-kid)Ť‰‰ (beep-on-terminal))Ť‰‰(t‰‰ Ť‰‰ (send self ':set-current-node left-kid)))))))Ť‰‰Ť; The following three methods are needed in case you :GO-DOWN or :GO-RIGHT, Ť; etc. to a node which lies off the screen.Ť;Ť(defmethod (chart-pane :scroll-if-necessary) ()Ť (if (or (send self ':fix-horizontal?)Ť‰ (send self ':fix-vertical?))Ť (send self ':refresh)Ť (send self ':update-blinker)))ŤŤ; If the node is on screen, this returns nil and nothing happens.Ť; If the node lies off-screen, the top-node is moved to compensate, Ť; and T is returned. Thus, :SCROLL-IF-NECESSARY will only refresh once,Ť; even if we need to scroll both horizontally and vertically.Ť;Ť; For a discussion on the existance of the 2's and the 7's in the code, see theŤ; documentation for the scrolling methods (e.g. :SCROLL-UP, :SCROLL-LEFT, etc.)Ť;Ť(defmethod (chart-pane :fix-horizontal?) ()Ť (let ((new-left (send current-node ':left))Ť‰(origin-left (send top-node ':left))Ť‰(right-boundary (- (send self ':width) Ť‰‰‰ 7 (send current-node ':width))))Ť (cond ((and (>= new-left 2) (<= new-left right-boundary))Ť‰ nil)‰‰‰‰‰; OK, return nilŤ‰ ((< new-left 2)Ť‰ (send top-node ':set-left (+ origin-left (- 2 new-left)))Ť‰ t)‰‰‰‰‰; Was bad, return tŤ‰ (tŤ‰ (send top-node ':set-left (- origin-left (- new-left right-boundary)))Ť‰ t))))‰‰‰‰; Was bad, return tŤŤ(defmethod (chart-pane :fix-vertical?) ()Ť (let ((new-top (send current-node ':top))Ť‰(origin-top (send top-node ':top))Ť‰(bottom-boundary (- (send self ':height) Ť‰‰‰ 7 (send current-node ':height))))Ť (cond ((and (>= new-top 2) (<= new-top bottom-boundary))Ť‰ nil)‰‰‰‰‰; OK, return nilŤ‰ ((< new-top 2)Ť‰ (send top-node ':set-top (+ origin-top (- 2 new-top)))Ť‰ t)‰‰‰‰‰; Was bad, return tŤ‰ (tŤ‰ (send top-node ':set-top (- origin-top (- new-top bottom-boundary)))Ť‰ t))))‰‰‰‰; Was bad, return tŤŤ(defmethod (chart-pane :add-below) ()Ť (send current-node ':add-below))ŤŤ(defmethod (chart-pane :add-right) ()Ť (send current-node ':add-right))ŤŤ(defmethod (chart-pane :add-left) ()Ť (send current-node ':add-left))ŤŤ(defmethod (chart-pane :add-above) ()Ť (send current-node ':add-above)) ŤŤ(defmethod (chart-pane :open) ()Ť (send current-node ':set-opened? t)Ť (send self ':refresh))ŤŤ(defmethod (chart-pane :open-below) ()Ť (loop for kid in (send current-node ':below)Ť‰do (send kid ':set-opened? t))Ť (send self ':refresh))ŤŤ(defmethod (chart-pane :close) ()Ť (send current-node ':set-opened? nil)Ť (send self ':refresh))ŤŤ(defmethod (chart-pane :close-below) ()Ť (loop for kid in (send current-node ':below)Ť‰do (send kid ':set-opened? nil))Ť (send self ':refresh)) Ť Ť(defmethod (chart-pane :edit) ()Ť (send current-node ':edit))ŤŤ(defmethod (chart-pane :make-this-top) ()Ť (cond ((let-user-confirm "Are you sure you want to wipe out everything above this node? ")Ť‰ (setq top-node current-node)Ť‰ (send self ':go-to-top))Ť‰(t nil)))ŤŤ(defmethod (chart-pane :remove-current) ()Ť (cond ((eq current-node top-node)Ť‰ (beep-on-terminal))Ť‰((let-user-confirm "Are you sure you want to wipe out this node? ")Ť‰ (send current-node ':remove-self))Ť‰(t nil)))Ť Ť(defmethod (chart-pane :remove-below) ()Ť (cond ((let-user-confirm "Are you sure you want to wipe out everybody under this node? ")Ť‰ (send current-node ':remove-below))Ť‰(t nil)))ŤŤ; First, compute DY (the amount to move up), and HERE (where you are now).Ť; By taking the MIN of the default *SCROLL-AMOUNT and our current-node'sŤ; position, you ensure you never move in a step large enough to takeŤ; your current node off the screen.Ť;Ť; "Why do you subtract 2?" you may ask... This ensures that you neverŤ; bring the current-node to a y-coordinate of less than +2, not zero.Ť; Leaving it at +2 gives it a few aesthetic pixels of upper border.Ť; Remember, your craftsmanship and attention to aesthetic detailŤ; really shows in applications programs like this.Ť;Ť(defmethod (chart-pane :scroll-up) ()Ť (let ((dy (min *scroll-amount (- (send current-node ':top) 2)))Ť‰(here (send top-node ':top)))Ť (send top-node ':set-top (- here dy))Ť (if (not (zerop dy)) (send self ':refresh))))Ť‰Ť; The 7 here is like the 2 above. It includes compensation for the border drawnŤ; around the current-node, plus the screen's blinker, which is a blinker ofŤ; TV:BOX-BLINKER flavor and thickness 2.Ť;Ť(defmethod (chart-pane :scroll-down) ()Ť (let ((dy (min *scroll-amountŤ‰‰ (- (send self ':height) 7Ť‰‰ (send current-node ':top) (send current-node ':height))))Ť‰(here (send top-node ':top)))Ť (send top-node ':set-top (+ here dy))Ť (if (not (zerop dy)) (send self ':refresh))))ŤŤ(defmethod (chart-pane :scroll-left) ()Ť (let ((dx (min *scroll-amount (- (send current-node ':left) 2)))Ť‰(here (send top-node ':left)))Ť (send top-node ':set-left (- here dx))Ť (if (not (zerop dx)) (send self ':refresh))))ŤŤ(defmethod (chart-pane :scroll-right) ()Ť (let ((dx (min *scroll-amountŤ‰‰ (- (send self ':width) 7Ť‰‰ (send current-node ':left) (send current-node ':width))))Ť‰(here (send top-node ':left)))Ť (send top-node ':set-left (+ here dx)) Ť (if (not (zerop dx)) (send self ':refresh))))ŤŤŤ;------------------------------------------------------------------------------Ť; The command paneŤ;ŤŤ(defflavor org-command-pane ()Ť‰ (tv:command-menu)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "ORG Command Pane")Ť (:default-init-plistŤ :font-map '(fonts:hl12bi)Ť :columns 4Ť :item-list *command-list))ŤŤ(defvar *column-1-commandsŤ '(("Save as File (c-S)" :save-as-fileŤ‰‰"Save current organization chart in a file")Ť‰ ("Read from File (c-R)" :restore-from-fileŤ‰‰"Restore organization chart previously saved in a file")Ť‰ ()Ť‰ ()Ť‰ ("Far Left (c-A)" :far-leftŤ‰‰"Go to the furthest left on this level")Ť‰ ("Far Right (c-E)" :far-rightŤ‰‰"Go to the furthest right on this level")Ť‰ ("Parameters (m-X)" :change-parametersŤ‰‰"Change the parameters for the whole chart")Ť‰ ("Edit This Node (c-X)" :editŤ‰‰"Edit this individual")))ŤŤ(defvar *column-2-commandsŤ '(("Add Below (h-N)" :add-belowŤ‰‰"Add a new inferior")Ť‰ ("Add Left (h-B)" :add-leftŤ‰‰"Add a new sibling to the left")Ť‰ ("Add Right (h-F)" :add-rightŤ‰‰"Add a new sibling to the right")Ť‰ ("Add Above (h-P)" :add-aboveŤ‰‰"Insert a new node above this one")Ť‰ ("Go Up (c-P)" :go-upŤ ‰‰"Move the current node upwards")Ť‰ ("Go Down (c-N)" :go-downŤ‰‰"Move the current node downwards")Ť‰ ("Go Left (c-B)" :go-leftŤ‰‰"Move the current node to the left")Ť‰ ("Go Right (c-F)" :go-rightŤ‰‰"Move the current node upwards")))ŤŤ(defvar *column-3-commandsŤ '(("Delete (c-D)" :remove-currentŤ‰‰"Delete exactly this node. (Keep its underlings, if any)")Ť‰ ("Delete Below (m-D)" :remove-belowŤ‰‰"Delete everything under this node")Ť‰ ("Go to the Top (m-<)" :go-to-topŤ‰‰"Go to the top of the chart")Ť‰ ()Ť‰ ("Scroll Up (m-P)" :scroll-upŤ‰‰"Move the display upwards")Ť‰ ("Scroll Down (m-N)" :scroll-downŤ‰‰"Move the display downwards")Ť‰ ("Scroll Left (m-B)" :scroll-leftŤ‰‰"Move the display to the left")Ť‰ ("Scroll Right (m-F)" :scroll-rightŤ‰‰"Move the display to the right")))ŤŤ(defvar *column-4-commandsŤ '(("Open (c-O)" :openŤ‰‰"Open up the current node")Ť‰ ("Open Below (m-O)" :open-belowŤ‰‰"Open up the underlings")Ť‰ ("Close (c-C)" :closeŤ‰‰"Close the current node")Ť‰ ("Close Below (m-C)" :close-belowŤ‰‰"Close the underlings")Ť‰ ()Ť‰ ()Ť‰ ("Make Bigger (c->)" :make-biggerŤ‰‰"Expand this chart")Ť‰ ("Make Smaller (c-<)" :make-smallerŤ‰‰"Shrink this chart")))ŤŤ(defun select-command-items (command-column)Ť (if (null command-column)Ť '("" :no-select nil)Ť `(,(first command-column)Ť‰ :eval (send *chart-pane ',(second command-column))Ť‰ :documentation ,(third command-column))))ŤŤ(defvar *command-listŤ (loop for command-column-1 in *column-1-commandsŤ for command-column-2 in *column-2-commandsŤ for command-column-3 in *column-3-commandsŤ for command-column-4 in *column-4-commandsŤ‰ collecting (select-command-items command-column-1)Ť‰ collecting (select-command-items command-column-2)Ť‰ collecting (select-command-items command-column-3)Ť‰ collecting (select-command-items command-column-4)))ŤŤ;;; Note that, in item-list values, ("" :no-select nil) can be used for dummyŤ;;; (blank) menu items.ŤŤŤ;------------------------------------------------------------------------------Ť;Ť; The pane at the bottom of the screenŤ;Ť(defflavor prompt-paneŤ‰()Ť‰(tv:pane-mixin tv:window))ŤŤ(defmethod (prompt-pane :after :refresh)(&rest ignore)Ť (send self ':home-cursor))ŤŤ;------------------------------------------------------------------------------Ť; Org Chart Frame: The master window with many panesŤ;ŤŤ(defflavor chart-frameŤ ()Ť (tv:process-mixin‰ Ť tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Organization Chart Program Frame")Ť (:default-init-plistŤ :expose-p t‰‰‰‰‰‰; expose w/o blink on instantiationŤ :activate-p t‰‰‰‰‰; activate on instantiationŤ :save-bits ':delayed‰‰‰‰‰; make save bits array on deexposureŤ :process '(org-initial-function)Ť :panes‰‰‰ Ť `((command-pane org-command-pane)Ť (chart-pane chart-pane)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ (command-pane chart-pane prompt-pane)‰‰; top, middle, bottomŤ ((command-pane :ask :pane-size))‰‰‰; As big as necessaryŤ ((prompt-pane 8 :lines))‰‰‰‰; 8 lines tallŤ ((chart-pane :even))))))‰‰‰‰; Whatever's left overŤŤ; Look at the :PROCESS init-keyword above (in the defflavor).Ť; This function gets run as the "initial form" of that process.Ť; It gets an infinite loop running which maintains the window.Ť;Ť(defun org-initial-function (window)Ť (send window ':loop))ŤŤ; This is org's top level loop.Ť; It does all the work of getting input from the user, and doingŤ; something intelligent with it.Ť;Ť(defmethod (chart-frame :loop) ()Ť (let* ((io (send self ':get-pane 'prompt-pane))Ť‰ (chart (send self ':get-pane 'chart-pane))Ť‰ (terminal-io io) Ť‰ (query-io io)Ť‰ (error-output io))Ť (loop for input = (send io ':any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤ‰‰ ((#\c-LŤ‰‰‰#+LMI #\clear-screen)Ť‰‰ (send chart ':refresh)Ť‰‰ (send io ':refresh))Ť‰‰ (#\c-F (send chart ':go-right))Ť‰‰ (#\c-B (send chart ':go-left))Ť‰‰ (#\c-P (send chart ':go-up))Ť‰‰ (#\c-N (send chart ':go-down))Ť‰‰ (#\c-A (send chart ':far-left))Ť‰‰ (#\c-E (send chart ':far-right))Ť‰‰ (#\m-F (send chart ':scroll-right))Ť‰‰ (#\m-B (send chart ':scroll-left))Ť‰‰ (#\m-P (send chart ':scroll-up))Ť‰‰ (#\m-N (send chart ':scroll-down))Ť‰‰ (#\h-F (send chart ':add-right))Ť‰‰ (#\h-B (send chart ':add-left))Ť‰‰ (#\h-P (send chart ':add-above))Ť‰‰ (#\h-N (send chart ':add-below))Ť‰‰ (#\c-D (send chart ':remove-current))Ť‰‰ (#\m-D (send chart ':remove-below))Ť‰‰ (#\c-O (send chart ':open))Ť‰‰ (#\m-O (send chart ':open-below))Ť‰‰ (#\c-C (send chart ':close))Ť‰‰ (#\m-C (send chart ':close-below))Ť‰‰ (#\c-S (send chart ':save-as-file))Ť‰‰ (#\c-R (send chart ':restore-from-file))Ť‰‰ (#\c-> (send chart ':make-bigger))Ť‰‰ (#\c-< (send chart ':make-smaller))Ť‰‰ (#\m-< (send chart ':go-to-top))Ť‰‰ (#\c-X (send chart ':edit))Ť‰‰ (#\end (send self ':bury))Ť‰‰ (#\m-X (send chart ':change-parameters))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input) ':execute (second input)))Ť‰‰ (t (beep))))))))ŤŤ;------------------------------------------------------------------------------Ť; Ť; This is how you get ORG up and running in the first placeŤ; Notice that this function always returns the same window,Ť; namely, *CHART-PANE. When you type System-O, it executesŤ; the function ORG, and selects whatever window is returnedŤ; be ORG.ŤŤ(defun org ()Ť (if (and (boundp '*chart-frame)Ť‰ (not (eq ':unbound *chart-frame))Ť‰ *chart-pane)Ť *chart-paneŤ ;else‰ Ť (setq *chart-frame (tv:make-window 'chart-frame))Ť (setq *chart-pane (send *chart-frame ':get-pane 'chart-pane))Ť (setq *command-pane (send *chart-frame ':get-pane 'command-pane))Ť (setq *prompt-pane (send *chart-frame ':get-pane 'prompt-pane))Ť *chart-pane))ŤŤ; This means you never have to type (org). Just type SYSTEM-O andŤ; it will find the chart-frame and display it for you.Ť;Ť(tv:add-system-key #\O '(org) "Organization Chart")ŤŤ; This will get printed whenever you load this fileŤŤ(format t "~%Org loaded. Type SYSTEM-O to begin.~2%")LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 2 :LENGTH-IN-BYTES 1859 :AUTHOR "SAM" :CREATION-DATE 2716754650 :QFASLP NIL :LENGTH 1859 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "OTHER" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤ;;;;OTHERŤŤ(require 'pattern-processing)Ť(require 'unification)Ť(provide 'other)ŤŤŤ(defun show-unifier-of (quasi-pattern1 quasi-pattern2Ť‰‰‰&optional (substitution (make-substitution)))Ť (multiple-value-bind (p1 var-pairs1) (patternize quasi-pattern1)Ť (multiple-value-bind (p2 var-pairs2) (patternize quasi-pattern2)Ť (let ((patterns (list p1 p2))Ť‰ (variable-lists (list (mapcar #'cdr var-pairs1)Ť‰‰‰‰ (mapcar #'cdr var-pairs2)))Ť‰ (s (unify? p1 p2 substitution)))Ť‰(if (null s)Ť‰ (format t "~%none~2%")Ť‰ (prognŤ‰ (dotimes (i 2)Ť‰ (dolist (var (nth i variable-lists))Ť‰‰(annotate-variable var (+ i 1))))Ť‰ (dotimes (i 2)Ť‰ (terpri)(terpri)Ť‰ (princ (express-pattern (nth i patterns)))Ť‰ (dolist (var (nth i variable-lists))Ť‰‰(show-annotated-bindings var s))Ť‰ (terpri)Ť‰ (princ (express-annotated-patternŤ‰‰ (instantiate-pattern (nth i patterns) s)))Ť‰ (terpri))))Ť‰(values)))))ŤŚŤ(defun annotate-variable (variable pattern-identifier)Ť (setf (get-from-variable variable 'in-pattern) pattern-identifier))ŤŤ(defun express-annotated-variable (variable)Ť (format nil "~A[~D]"Ť‰ (variable-name variable)Ť‰ (get-from-variable variable 'in-pattern)))ŤŤ(defun show-annotated-bindings (variable substitution)Ť (do ((p nil)) (nil)Ť (format t (if (null p) "~%~5T" "~5,10T = "))Ť (format t "~A" (express-annotated-pattern variable))Ť (setf p (or (get-binding-pair variable substitution) (return))Ť‰ variable (binding-value p))))ŤŤ(defun express-annotated-pattern (pattern)Ť (pattern-copy pattern #'express-annotated-variable))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 7 :LENGTH-IN-BYTES 6587 :AUTHOR "wilde" :CREATION-DATE 2716346243 :QFASLP NIL :LENGTH 6587 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "PAINT" :TYPE "LISP" :VERSION 2) ŤŤŤŤŤŤŤŤ;;; PAINTŤ;;; by LMI Education DivisionŤŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ;;; To paint on a window with the mouse, first load this file and evaluateŤ;;; (paint) .ŤŤ;;; Notice that the predicate screen-displays-1-bits-as-black-p is not veryŤ;;; portable because it is standing in for apparently absent systemŤ;;; (supportable) software that abstracts away from the details ofŤ;;; particular machines.ŤŤ(defun screen-displays-1-bits-as-black-pŤ (&OPTIONAL (SCREEN tv:DEFAULT-SCREEN))Ť "There being apparently no Zetalisp-defined function to check whether theŤ display hardware currently displays a screen's 1-bits as black or asŤ white, this function pretends to be it. The uppercase code,Ť ** (c) Copyright 1980, 1981 Massachusetts Institute of Technology **,Ť is taken from the definitions in the TV package of BLACK-ON-WHITE,Ť WHITE-ON-BLACK, and COMPLEMENT-BOW-MODE, which each have such code, foundŤ in the file LAM3:QL.WINDOW;SHWARM.LISP#339 ."Ť (SELECT tv:PROCESSOR-TYPE-CODEŤ (SI:CADR-TYPE-CODEŤ (logtest 1_2 (%XBUS-READ (tv:SCREEN-CONTROL-ADDRESS SCREEN))))Ť (SI:LAMBDA-TYPE-CODEŤ (logtest 1_4 (%NUBUS-READ TV:TV-QUAD-SLOT 4)))))ŤŤŤŤŤŤŚŤŤŤŤŤŤ(defvar *window-video-was-reversed?* :unboundŤ‰ "the window's video setting as this program first found it")Ť(defconst *default-to-reverse-video?* nilŤ‰ "whether to begin with the window's video reversed")ŤŤ(defconst *brush-shapes* '(square circle line-\ line-//)Ť‰ "list of brush shapes that are defined")Ť(defconst *default-brush-shape* 'circle "brush shape to begin with")Ť(defvar *brush-shape*‰‰:unbound "current brush shape")ŤŤ(defconst *default-brush-size* 16 "brush size to begin with")Ť(defvar *brush-size*‰ :unbound "current brush size")ŤŤ(defconst *ink-modes* '(draw erase blacken whiten blink-ink)Ť‰ "list of ink modes that are defined; Draw and erase generateŤ‰ figure and ground, respectively, as appropriate to theŤ‰ window's video setting. Blacken and whiten do so absolutely.Ť‰ Blink-ink complements what it is painted onto, and appears toŤ‰ blink when successive brush strokes overlap.")Ť(defconst *default-ink-mode* 'draw "ink mode to begin with")Ť(defvar *ink-mode*‰ :unbound "current ink mode")ŤŤ(defconst *paint-menu-item-list*Ť '(("Square"‰:value‰‰squareŤ ‰‰:documentation‰"Use a square paintbrush.")Ť ("Circle"‰:value‰‰circleŤ‰ ‰:documentation‰"Use a circular paintbrush.")Ť ("Line-\"‰:value‰‰line-\Ť ‰‰:documentation‰"Use a \ paintbrush.")Ť ("Line-//"‰:value‰‰line-//Ť ‰‰:documentation‰"Use a // paintbrush.")Ť ("BIGGER"‰:value‰‰biggerŤ‰ ‰:documentation‰"Increase size of brush.")Ť ("SMALLER"‰:value‰‰smallerŤ‰ ‰:documentation‰"Decrease size of brush.")Ť ("DRAW"‰:value‰‰drawŤ ‰‰:documentation‰"Draw as you stroke.")Ť ("ERASE"‰:value‰‰eraseŤ ‰‰:documentation‰"Erase as you stroke.")Ť ("CLEAR"‰:value‰‰clearŤ ‰‰:documentation‰"Clear the window.")Ť ("COMPLEMENT IMAGE" :value‰complementŤ‰ ‰:documentation‰"Reverse figure and ground.")Ť ("BLACKEN"‰:value‰‰blackenŤ ‰‰:documentation‰"Blacken as you stroke.")Ť ("WHITEN"‰:value‰‰whitenŤ ‰‰:documentation‰"Whiten as you stroke.")Ť ("BLINK-INK" :value‰‰blink-inkŤ‰ ‰:documentation‰"Blink-ink as you stroke.")Ť ("EXIT"‰:value‰‰exitŤ ‰‰:documentation‰"Exit.")))Ť(defconst *sticky-items* '(bigger smaller complement)Ť "menu items that once chosen become the new default choice")ŤŚŤŤŤŤŤŤ(defun paint ()Ť (initialize-window)Ť (initialize-paintbrush)Ť (do ((default-choice nil)Ť (item-value nil)Ť (item-itself))Ť ((eq item-value 'exit) (restore-window) t)Ť (make-dynamic-changes)Ť (multiple-value (item-value item-itself)Ť (tv:menu-chooseŤ‰*paint-menu-item-list* "palette" '(:mouse) default-choice))Ť (if (memq item-value *sticky-items*) (setq default-choice item-itself))Ť (make-static-change item-value)))ŤŤ(defun initialize-window ()Ť (setq *window-video-was-reversed?*Ť‰(send tv:selected-window ':reverse-video-p))Ť (send tv:selected-window ':set-reverse-video-pŤ‰*default-to-reverse-video?*)Ť (send tv:selected-window ':clear-screen))ŤŤ(defun restore-window ()Ť (send tv:selected-window ':clear-screen)Ť (send tv:selected-window ':set-reverse-video-pŤ‰*window-video-was-reversed?*))ŤŤ(defun complement-video-of-window ()Ť (send tv:selected-window ':set-reverse-video-pŤ‰(not (send tv:selected-window ':reverse-video-p))))ŤŤ(defun initialize-paintbrush ()Ť (setq *brush-shape*‰*default-brush-shape*Ť‰*brush-size*‰*default-brush-size*Ť‰*ink-mode*‰*default-ink-mode*))ŤŤ(defun make-static-change (item-value)Ť (cond ((memq item-value *brush-shapes*)Ť‰ (setq *brush-shape* item-value))Ť‰((memq item-value *ink-modes*)Ť‰ (setq *ink-mode* item-value))Ť‰(tŤ‰ (selectq item-valueŤ‰ (bigger‰(setq *brush-size* (* 2 *brush-size*)))Ť‰ (smaller‰(if (> *brush-size* 1)Ť‰‰‰ (setq *brush-size* (// *brush-size* 2))))Ť‰ (complement‰(complement-video-of-window))Ť‰ (clear‰(send tv:selected-window ':clear-screen))))))ŤŚŤŤŤŤŤŤ(defun make-dynamic-changes ()Ť (tv:with-mouse-grabbedŤ (setq tv:who-line-mouse-grabbed-documentationŤ‰ "L: Stroke the brush. M: Get menu.")Ť (do* ((size-X-2 (* *brush-size* 2))Ť‰ (dummy (tv:mouse-wait) (tv:mouse-wait x y buttons))Ť‰ (x tv:mouse-x tv:mouse-x)Ť‰ (y tv:mouse-y tv:mouse-y)Ť‰ (buttons tv:mouse-last-buttons tv:mouse-last-buttons)Ť‰ (alu (get-alu) (get-alu)))Ť‰ (nil)Ť (selectq buttonsŤ‰(1 (selectq *brush-shape*Ť‰ (square (send tv:selected-window ':draw-rectangleŤ‰‰‰ size-X-2 size-X-2Ť‰‰‰ (- x *brush-size*) (- y *brush-size*) alu))Ť‰ (circle (send tv:selected-window ':draw-filled-in-circleŤ‰‰‰ x y *brush-size* alu))Ť‰ (line-\ (send tv:selected-window ':draw-lineŤ‰‰‰ (- x *brush-size*) (- y *brush-size*)Ť‰‰‰ (+ x *brush-size*) (+ y *brush-size*) alu))Ť‰ (line-// (send tv:selected-window ':draw-lineŤ‰‰‰ (- x *brush-size*) (+ y *brush-size*)Ť‰‰‰ (+ x *brush-size*) (- y *brush-size*) alu))))Ť‰(2 (return))Ť‰(4 nil)))))ŤŤ(defun get-alu ()Ť "Given the screen's current hardware display setting, the window'sŤ current video setting, and the current ink mode, get appropriate aluŤ function."Ť (selectq *ink-mode*Ť (draw‰(send tv:selected-window ':tv:char-aluf))Ť (erase‰(send tv:selected-window ':tv:erase-aluf))Ť (blacken‰(if (screen-displays-1-bits-as-black-p)Ť‰‰ tv:alu-iorŤ‰‰ tv:alu-andca))Ť (whiten‰(if (screen-displays-1-bits-as-black-p)Ť‰‰ tv:alu-andcaŤ‰‰ tv:alu-ior))Ť (blink-ink‰tv:alu-xor)))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 10 :LENGTH-IN-BYTES 9332 :AUTHOR "SAM" :CREATION-DATE 2716749161 :QFASLP NIL :LENGTH 9332 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "PATTERN-PROCESSING" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;PATTERN PROCESSINGŤŤ(require 'pattern-definition)Ť(require 'variable-substitution)Ť(provide 'pattern-processing)ŤŤŤ;;; Consider a PATTERN to be anything isomorphic in structure (or at leastŤ;;; operationally isomorphic in the way it is composed and decomposed) to aŤ;;; linked (and possibly nested, possibly dotted) list, except that eachŤ;;; ultimate (atomic) component is either a constant or a pattern variable.Ť;;; That is, the operational structure of a pattern is that of a binaryŤ;;; external tree with variables. Ť;;;Ť;;; We want to treat all occurrences of the same variable within aŤ;;; specified (sub)pattern as identical to each other, yet distinct fromŤ;;; all other occurrences of variables within or outside of that pattern.Ť;;; The specified pattern is the SCOPE of the variable. The most flexibleŤ;;; Lisp comparison predicate for this purpose is EQ, so let us require allŤ;;; occurrences of a pattern variable to be EQ within its scope, and not EQŤ;;; to any other variables -- or other patterns -- within or outside itsŤ;;; scope. Ť;;;Ť;;; To provide for facile printed representations of patterns, let aŤ;;; QUASI-PATTERN be a would-be pattern that contains some QUASI-VARIABLESŤ;;; in place of true pattern variables. All occurrences of aŤ;;; quasi-variable must be EQUAL within a quasi-pattern, and not EQUAL toŤ;;; any other quasi-variables or pattern variables within thatŤ;;; quasi-pattern. Then that quasi-pattern may be associated with (andŤ;;; converted to and from) a true pattern where each quasi-variable isŤ;;; converted to a pattern variable whose scope is the entire pattern.Ť;;;Ť;;; Two patterns match if they are EQ, or one is atomic and a matchingŤ;;; predicate says it matches the other, or their corresponding componentsŤ;;; match. The matching predicate for constants must be some symmetricalŤ;;; test of equality. Particular applications may introduce differentŤ;;; criteria.ŤŚŤ;;; A module PROVIDEs a PATTERN-DEFINITION as REQUIREd above iff itŤ;;; provides the following functions which define patterns andŤ;;; quasi-patterns:Ť;;;Ť;;; QUASI-VARIABLE (variable-name) "Given a variable-name string,Ť;;; return a correspondingŤ;;; quasi-variable."Ť;;;Ť;;; QUASI-VARIABLE-P (x) "Is this a quasi-variable?"Ť;;;Ť;;; QUASI-VARIABLE-NAME (quasi- "Given a quasi-variable, return itsŤ;;; variable) name as a string."Ť;;;Ť;;;Ť;;; MAKE-VARIABLE (variable-name "Make a pattern variable, given aŤ;;; &optional variable-name string andŤ;;; plist-contents) optionally the contents of aŤ;;; property-list."Ť;;;Ť;;; VARIABLE-P (x) "Is this a pattern variable?"Ť;;;Ť;;; VARIABLE-NAME (variable) "Given a pattern variable, returnŤ;;; its name as a string."Ť;;;Ť;;; GET-FROM-VARIABLE (variable key "Return the value of patternŤ;;; &rest other- variable VARIABLE's KEY property.Ť;;; args-to-getf) This function is SETF-able."Ť;;;Ť;;;Ť;;; MAKE-VARIABLE-FOR (quasi- "Given a quasi-variable, make aŤ;;; variable) corresponding pattern variable."Ť;;;Ť;;; COPY-VARIABLE (variable "Make a copy of a pattern variable,Ť;;; &optional the copy optionally inheriting aŤ;;; copy-plist-p) copy of the variable'sŤ;;; property-list."Ť;;;Ť;;; QUASI-VARIABLE-FOR (variable) "Given a pattern variable, return aŤ;;; corresponding quasi-variable."Ť;;;Ť;;;Ť;;; CONSTANT-P (pattern)Ť;;;Ť;;; ATOMIC-P (pattern)Ť;;; COMPOSITE-P (pattern)Ť;;; MAKE-COMPOSITE (next-component rest-of-components)Ť;;; NEXT-COMPONENT (composite-pattern)Ť;;; REST-OF-COMPONENTS (composite-pattern)Ť;;;Ť;;; MATCH-CONSTANT-P (constant pattern) "Does CONSTANT match PATTERN?Ť;;; This is a symmetrical test ofŤ;;; equality."Ť;;; MATCH-VARIABLE-P (variable pattern)ŤŚŤ;;; Functions or options of functions dealing with variable names andŤ;;; property lists may be omitted, but they are desirable and may beŤ;;; required for some applications.Ť;;;Ť;;; See the LIST-PATTERNS module for an example of a module which providesŤ;;; a PATTERN-DEFINITION.ŤŚŤ(defun patternize (quasi-pattern &aux (alist nil) v)Ť "Given a would-be pattern that contains quasi-variables, return aŤ corresponding true pattern where all quasi-variables have beenŤ uniquified. That is, for each quasi-variable, all occurrences of whichŤ must be EQUAL to each other, its corresponding pattern variable is EQ toŤ all -- and only -- other occurrences in the resulting pattern.Ť As a second value, we return an alist of quasi-variables and theirŤ corresponding pattern variables."Ť (labels ((variable-for (quasi-variable)Ť‰ (or (cdr (assoc quasi-variable alist :test #'equal))Ť‰‰ (prog1 (setq v (make-variable-for quasi-variable))Ť‰‰‰(push (cons quasi-variable v) alist))))Ť‰ (copy (pat)Ť‰ (cond ((quasi-variable-p pat) (variable-for pat))Ť‰‰ ((atomic-p pat) pat)Ť‰‰ ((make-composite (copy (next-component pat))Ť‰‰‰‰ (copy (rest-of-components pat)))))))Ť (values (copy quasi-pattern) (nreverse alist))))ŤŤ(defun pattern-copy (pattern substitution-function)Ť "Given a pattern, return a copy where each occurrence of a variable isŤ replaced by the return value of a substitution-function applied to thatŤ occurrence."Ť (labelsŤ ((copy (pat)Ť‰ (cond ((constant-p pat) pat)Ť‰ ((variable-p pat) (funcall substitution-function pat))Ť‰ ((make-composite (copy (next-component pat))Ť‰‰‰‰(copy (rest-of-components pat)))))))Ť (copy pattern)))ŤŤ(defun pattern-copy-variables-uniquely (pattern substitution-functionŤ‰‰‰‰‰&aux (alist nil) x)Ť "Given a pattern, return a copy where each variable is replaced in allŤ its occurrences by a single object -- the return value of aŤ substitution-function applied to that variable.Ť As a second value, we return an alist of replaced variables and theirŤ replacements."Ť (labels ((replacement-for (variable)Ť‰ (if (setq x (assoc variable alist :test #'eq))Ť‰ (cdr x)Ť‰ (prog1 (setq x (funcall substitution-function variable))Ť‰‰ (if (not (eq x variable))Ť‰‰‰(push (cons variable x) alist))))))Ť (values (pattern-copy pattern #'replacement-for) (nreverse alist))))ŤŤ(defun copy-pattern (pattern)Ť "Given a pattern, return a copy with corresponding but independentŤ variables. As a second value, we return an alist of old variables andŤ their corresponding new variables."Ť (pattern-copy-variables-uniquely pattern #'copy-variable))ŤŚŤ(defun instantiate-pattern (pattern substitution &optional hold-the-vars-pŤ‰‰‰ &aux (alist nil) x)Ť "Given a PATTERN, return a copy wherein any variable that is bound inŤ SUBSTITUTION has been recursively replaced by its value pattern, suchŤ that all remaining variables are unbound. Optionally, don't replace anyŤ variable whose ultimate value is also a variable.Ť As a second value, we return an alist of replaced variables and theirŤ replacements."Ť (labelsŤ ((replacement-for (variable)Ť‰ (if (setq x (assoc variable alist :test #'eq))Ť‰ (cdr x)Ť‰ (prog1 (setq x (instantiation-of variable))Ť‰‰ (if (not (eq x variable))Ť‰‰ (push (cons variable x) alist)))))Ť (instantiation-of (variable)Ť‰ (setq x (get-ultimate-value variable substitution))Ť‰ (if (if (not hold-the-vars-p) (eq x variable) (variable-p x))Ť‰ variableŤ‰ (pattern-copy x #'replacement-for))))Ť (values (pattern-copy pattern #'replacement-for) (nreverse alist))))ŤŤ(defun pattern-equal (pattern1 pattern2 &aux (alist (ncons nil)) pair)Ť "Do PATTERN1 and PATTERN2 match up to a one-for-one replacement ofŤ variables? Truth is represented by a non-NIL alist of correspondingŤ variables."Ť (labels ((prior-pair? (var1 var2)Ť‰ (dolist (pair alist nil)Ť‰ (when pairŤ‰‰ (if (or (eq var1 (car pair)) (eq var2 (cdr pair)))Ť‰‰ (return pair)))))Ť‰ (match-var-p (var pat)Ť‰ (when (variable-p pat)Ť‰ (if (setq pair (prior-pair? var pat))Ť‰‰ (and (eq var (car pair)) (eq pat (cdr pair)))Ť‰‰ (push (cons var pat) alist))))Ť‰ (pat= (pat1 pat2)Ť‰ (cond ((constant-p pat1) (match-constant-p pat1 pat2))Ť‰‰ ((constant-p pat2) nil)Ť‰‰ ((variable-p pat1) (match-var-p pat1 pat2))Ť‰‰ ((variable-p pat2) nil)Ť‰‰ ((and (pat= (next-component pat1)Ť‰‰‰ (next-component pat2))Ť‰‰‰ (pat= (rest-of-components pat1)Ť‰‰‰ (rest-of-components pat2)))))))Ť (if (pat= pattern1 pattern2) alist)))ŤŤ(defun express-pattern (pattern)Ť "Given a pattern, return a copy where each occurrence of a patternŤ variable is replaced by a corresponding quasi-variable."Ť (pattern-copy pattern #'quasi-variable-for))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 2 :LENGTH-IN-BYTES 1746 :AUTHOR "SAM" :CREATION-DATE 2721878642 :QFASLP NIL :LENGTH 1746 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "PREDICATE-CALCULUS" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;PREDICATE CALCULUSŤŤ(require 'defining)Ť(require 'pattern-definition)Ť(require 'pattern-processing)Ť(provide 'predicate-calculus)ŤŚŤ;;; TermsŤŤ(defmacro make-quasi-function-term (quasi-function-symbol quasi-terms)Ť `(make-composite ,quasi-function-symbol ,quasi-terms))ŤŤ(defmacro function-term-function-symbol (function-term)Ť `(next-component ,function-term))ŤŤ(defmacro function-term-terms (function-term)Ť `(rest-of-components ,function-term))ŤŤŤŤ;;; Atomic FormulasŤŤ(defmacro make-quasi-atom (quasi-predicate-symbol quasi-terms)Ť `(make-composite ,quasi-predicate-symbol ,quasi-terms))ŤŤ(defmacro atom-predicate-symbol (atomic-formula)Ť `(next-component ,atomic-formula))ŤŤ(defmacro atom-terms (atomic-formula)Ť `(rest-of-components ,atomic-formula))ŤŤŤŤ;;; Horn ClausesŤ;;;Ť;;; Consider only Prolog Horn clauses, which have exactly one conclusion.ŤŤ(defmacro make-quasi-Horn-clause (quasi-head quasi-body)Ť `(make-composite ,quasi-head ,quasi-body))ŤŤ(defmacro Horn-clause-head (Horn-clause)Ť `(next-component ,Horn-clause))ŤŤ(defmacro Horn-clause-body (Horn-clause)Ť `(rest-of-components ,Horn-clause))ŤŤŤŤ;;; VariantsŤŤ(alias variants? pattern-equalŤ "Do FORMULA1 and FORMULA2 subsume each other as patterns? That is, forŤ each does there exist a substitution which when applied to it -- withoutŤ recursion -- yields the other? If so, they match up to a one-for-oneŤ replacement of variables, and we return a non-NIL alist of correspondingŤ variables.")ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 5 :LENGTH-IN-BYTES 4346 :AUTHOR "wilde" :CREATION-DATE 2716346292 :QFASLP NIL :LENGTH 4346 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "PROCESS-BRINGUP-WINDOW" :TYPE "LISP" :VERSION 4) ;;; -*- Mode:LISP; Package:USER; Fonts:(BIGFNT); Base:10 -*-ŤŤ; Title: ProcessesŤ; Subtitle: Process to bring up a windowŤ; File name: process-bringup-window.lisp and .qfaslŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; To demo, execute (process-make-a-window) ŤŤŤ; Write a process to bring up a window.ŤŤ; First, define a simple window.Ť; Notice that we have included tv:process-mixin as a componentŤ; flavor.ŤŤŤ(defflavor simple-process-windowŤ‰ ()Ť‰ (tv:process-mixin tv:window)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:default-init-plistŤ :borders 2Ť :label '(:top :centered :string "Simple Process Window")Ť :more-p nil))ŤŤŤŤ; Write a function to make a process with the window as aŤ; run reason.ŤŤ; After the process is made, we send it a :preset message.Ť; :preset should be followed by a function name (the process'sŤ; initial function) and arguments to be passed to that function.Ť; :preset sets the process's initial function and its arguments.Ť; The process is then reset so that it will throw out of anyŤ; current computation and start itself up by applying the Ť; function to the arguments. A :preset operation on a stopped Ť; process will return immediately, but will not activate theŤ; process; hence the process will not really apply the function Ť; to its arguments until it is activated later.ŤŤ; The function process-reset-and-enable resets the process,Ť; then enables it.ŤŤŤ(defun process-make-a-window (&aux this-process window)Ť (setq this-processŤ‰(make-process 'this-processŤ‰‰ ':run-reasonsŤ‰‰ (setq windowŤ‰‰‰ (make-instanceŤ‰‰‰ 'simple-process-window))))Ť (send window ':activate)Ť (send window ':expose)Ť (send window ':select)Ť (send this-process ':preset 'qix window)Ť (process-reset-and-enable this-process))ŤŤŤŤ; The initial function for this process is qix, which wasŤ; adapted from hacks:qix. It stops when something is typed on Ť; the keyboard.Ť; To get out of the window, just select another one.ŤŤŤ(defun qix (streamŤ‰ &aux (length 100) (times nil))Ť (let* ((list (make-list (1+ length)))Ť‰ (history (nthcdr (1- length) list)))Ť (%p-store-cdr-code (cdr history) cdr-error)Ť (%p-store-cdr-code history cdr-normal)Ť (rplacd history list)Ť (send stream ':clear-screen)Ť (loop repeat lengthŤ‰ for h = history then (cdr h)Ť‰ do (setf (car h) (make-list 4)))Ť (multiple-value-bind (xlim ylim)Ť‰(send stream ':inside-size)Ť (loop with x1 = 0Ť‰ and y1 = (1- ylim)Ť‰ and x2 = 0Ť‰ and y2 = (1- ylim)Ť‰ and dx1 = 5Ť‰ and dy1 = 12Ť‰ and dx2 = 12Ť‰ and dy2 = 5Ť‰ with temŤ‰ until (or (send stream ':tyi-no-hang)Ť‰‰ (if times (= (setq times (1- times)) 0)Ť‰‰‰nil))Ť‰ when (caar history)Ť‰ do (send stream ':draw-lineŤ‰‰ (first (car history))Ť‰‰ (second (car history))Ť‰‰ (third (car history))Ť‰‰ (fourth (car history))Ť‰‰ tv:alu-xor)Ť‰ do (setf (first (car history)) x1)Ť‰ (setf (second (car history)) y1)Ť‰ (setf (third (car history)) x2)Ť‰ (setf (fourth (car history)) y2)Ť‰ (setq history (cdr history))Ť‰ (send stream ':draw-line x1 y1 x2 y2 tv:alu-xor)Ť‰ (setq dx1 (1- (+ dx1 (random 3)))Ť‰‰ dy1 (1- (+ dy1 (random 3)))Ť‰‰ dx2 (1- (+ dx2 (random 3)))Ť‰‰ dy2 (1- (+ dy2 (random 3))))Ť‰ (cond ((> dx1 12) (setq dx1 12))Ť‰‰ ((< dx1 -12) (setq dx1 -12)))Ť‰ (cond ((> dy1 12) (setq dy1 12))Ť‰‰ ((< dy1 -12) (setq dy1 -12)))Ť‰ (cond ((> dx2 12) (setq dx2 12))Ť‰‰ ((< dx2 -12) (setq dx2 -12)))Ť‰ (cond ((> dy2 12) (setq dy2 12))Ť‰‰ ((< dy2 -12) (setq dy2 -12)))Ť‰ (cond ((or ( (setq tem (+ x1 dx1)) xlim)Ť‰‰ (minusp tem))Ť‰‰ (setq dx1 (- dx1))))Ť‰ (cond ((or ( (setq tem (+ x2 dx2)) xlim)Ť‰‰ (minusp tem))Ť‰‰ (setq dx2 (- dx2))))Ť‰ (cond ((or ( (setq tem (+ y1 dy1)) ylim)Ť‰‰ (minusp tem))Ť‰‰ (setq dy1 (- dy1))))Ť‰ (cond ((or ( (setq tem (+ y2 dy2)) ylim)Ť‰‰ (minusp tem))Ť‰‰ (setq dy2 (- dy2))))Ť‰ (setq x1 (+ x1 dx1)Ť‰‰ y1 (+ y1 dy1)Ť‰‰ x2 (+ x2 dx2)Ť‰‰ y2 (+ y2 dy2))Ť‰ finally (loop repeat lengthŤ‰‰‰ when (caar history)Ť‰‰‰ do (send stream ':draw-lineŤ‰‰‰‰ (first (car history))Ť‰‰‰‰ (second (car history))Ť‰‰‰‰ (third (car history))Ť‰‰‰‰ (fourth (car history))Ť‰‰‰‰ tv:alu-xor)Ť‰‰‰ do (setq history (cdr history)))))))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 11 :LENGTH-IN-BYTES 10438 :AUTHOR "SAM" :CREATION-DATE 2721882036 :QFASLP NIL :LENGTH 10438 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "PROLOG" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤ;;;;PROLOGŤŤ(require 'unification)Ť(require 'predicate-calculus)Ť(require 'streams)Ť(require 'pattern-processing)Ť(provide 'Prolog)ŤŚŤ;;;;Database ManagementŤŤŤ(defmacro make-database () `(list* 'database nil))Ť(defmacro database-contents (database) `(cdr ,database))ŤŤ(defvar *Prolog-database* (make-database)Ť "current Prolog database of assertions")ŤŤ(defmacro with-database ((database) &body body)Ť `(let ((*Prolog-database* ,database)) ,@body))ŤŤ(defmacro db () `(database-contents *Prolog-database*))ŤŤŤ(defun clear-db () (setf (db) nil))ŤŤ(defmacro add-to-db (assertion) `(push ,assertion (db)))ŤŤ(defmacro add-in-order-to-db (assertions)Ť `(dolist (assertion (reverse ,assertions)) (add-to-db assertion)))ŤŤ(defmacro delete-from-dbŤ‰ (assertion &key (test '#'variants?) (count nil count-provided-p))Ť `(setf (db) (delete ,assertion (db) :test ,testŤ‰‰ ,@(if count-provided-p (list :count count)))))ŤŤ(defmacro delete-em-from-db (assertions &rest key-pairs)Ť `(dolist (assertion ,assertions) (delete-from-db assertion ,@key-pairs)))ŤŤ(defmacro fetch-from-db (fetch-pattern)Ť (declare (ignore fetch-pattern)) `(db))ŤŤ(defmacro probe-db (assertion-pattern &key (test '#'variants?))Ť (let ((pattern (make-symbol "pattern")))Ť `(let ((,pattern ,assertion-pattern))Ť (remove ,pattern (fetch-from-db ,pattern) :test-not ,test))))ŤŤŤ(defun assert-to-db (assertion)Ť (delete-from-db assertion :count 1)Ť (add-to-db assertion))ŤŤ(defun assert-in-order-to-db (assertions)Ť (delete-em-from-db assertions :count 1)Ť (add-in-order-to-db assertions))ŤŤ(defmacro retract-from-db (assertion)Ť `(delete-from-db ,assertion :count 1))ŤŤ(defmacro retract-em-from-db (assertions)Ť `(delete-em-from-db ,assertions :count 1))ŤŤ(defmacro candidate-assertions (goal) `(fetch-from-db ,goal))ŤŚŤ;;;;User InterfaceŤŤŤ(defmacro clear-database () `(progn (clear-db) (values)))ŤŤ(defmacro my-assert (quasi-assertion)Ť `(progn (assert-to-db (patternize ',quasi-assertion)) (values)))ŤŤ(defmacro assert-em (&rest quasi-assertions)Ť `(progn (assert-in-order-to-db (mapcar #'patternize ',quasi-assertions))Ť‰ (values)))ŤŤ(defmacro retract (quasi-assertion)Ť `(progn (retract-from-db (patternize ',quasi-assertion)) (values)))ŤŤ(defmacro retract-em (&rest quasi-assertions)Ť `(progn (retract-em-from-db (mapcar #'patternize ',quasi-assertions))Ť‰ (values)))ŤŤ(defmacro show-patterns (patterns)Ť `(dolist (pattern ,patterns (values)) (print (express-pattern pattern))))ŤŤ(defmacro show-database ()Ť `(show-patterns (fetch-from-db (make-variable ""))))ŤŤ(defmacro make-Horn-clause-probe (predicate-symbol)Ť `(patternize (make-quasi-Horn-clauseŤ‰‰ (make-quasi-atom ,predicate-symbol (make-variable ""))Ť‰‰ (make-variable ""))))ŤŤ(defmacro probe (predicate-symbol)Ť `(show-patterns (probe-db (make-Horn-clause-probe ',predicate-symbol)Ť‰‰‰ :test #'unify?)))ŤŤ(defmacro define-predicate (predicate-symbol &body quasi-Horn-clauses)Ť `(def-predicate ',predicate-symbol ',quasi-Horn-clauses))ŤŤ(defun def-predicate (predicate-symbol quasi-Horn-clauses)Ť (unless (and (symbolp predicate-symbol)Ť‰ (not (variable-p (patternize predicate-symbol))))Ť (error "In a pattern, ~S is not a constant symbol." predicate-symbol))Ť (dolist (q-H-c quasi-Horn-clauses)Ť (unless (eq (atom-predicate-symbol (Horn-clause-head q-H-c))Ť‰‰predicate-symbol)Ť (errorŤ‰"Invalid predicate symbol ~S in head of clause of predicate ~S ."Ť‰(atom-predicate-symbol (Horn-clause-head q-H-c))Ť‰predicate-symbol)))Ť (delete-from-db (make-Horn-clause-probe predicate-symbol) :test #'unify?)Ť (assert-in-order-to-db (mapcar #'patternize quasi-Horn-clauses))Ť (values))ŤŤ(defmacro undefine-predicate (predicate-symbol)Ť `(def-predicate ',predicate-symbol nil))ŤŚŤ(defvar *trace-prolog* nil)ŤŤ(defmacro query (quasi-goal &optional (trace-p '*trace-prolog*))Ť `(query-db ',quasi-goal ,trace-p))ŤŤ(defmacro express-instance (pattern substitution)Ť `(express-pattern (instantiate-pattern ,pattern ,substitution t)))ŤŤ#|Ť(defun query-db (quasi-goal &optional (*trace-prolog* *trace-prolog*)Ť‰‰ &aux (goal (patternize quasi-goal))Ť‰‰ (proofs (proofs-of goal)))Ť (valuesŤ (mapcar #'(lambda (substitution) (express-instance goal substitution))Ť‰ proofs)Ť proofs))Ť|#ŤŤŤ(defun query-db (quasi-goal &optional (*trace-prolog* *trace-prolog*))Ť (multiple-value-bind (goal var-pairs) (patternize quasi-goal)Ť (let ((vars (mapcar #'cdr var-pairs))Ť‰ (proofs (proofs-of goal))Ť‰ (quasi-replies nil))Ť (if (null proofs)Ť‰(format t "~%none~2%")Ť‰(prognŤ‰ (terpri)(terpri)Ť‰ (dolist (proof proofs)Ť‰ (print (express-pattern goal))Ť‰ (dolist (var vars) (show-bindings var proof))Ť‰ (push (print (express-instance goal proof)) quasi-replies)Ť‰ (terpri)(terpri))Ť‰ (nreverse quasi-replies)))Ť (values))))ŤŤ(defun show-bindings (variable substitution)Ť (do ((p nil)) (nil)Ť (format t (if (null p) "~%~5T" "~5,10T = "))Ť (format t "~A" (express-pattern variable))Ť (setf p (or (get-binding-pair variable substitution) (return))Ť‰ variable (binding-value p))))ŤŤ(defun proofs-of (goal)Ť (catch 'proofs-ofŤ (prove goal (candidate-assertions goal) (make-substitution))))ŤŚŤ;;;;TracingŤŤŤ(defvar *proof-level* 0)Ť(defvar *indent* 0)ŤŤ(defmacro with-trace ((goal assertion old-sub new-sub) &body body)Ť (let ((proofs (make-symbol "proofs")))Ť `(progn (prologue ,goal ,assertion ,old-sub ,new-sub)Ť‰ (let ((,proofs (let* ((*proof-level* (+ *proof-level* 1))Ť‰‰‰‰ (*indent* (* 3 *proof-level*)))Ť‰‰‰ ,@body)))Ť‰ (epilogue ,goal ,assertion ,new-sub ,proofs)Ť‰ ,proofs))))ŤŤ(defun prologue (goal assertion old-sub new-sub)Ť (when (and new-sub *trace-prolog*)Ť (format t "~%~v,0TCan prove: ~A with assertion ~A" *indent*Ť‰ (express-instance goal old-sub) (express-pattern assertion))Ť (if (Horn-clause-body assertion)Ť (format t "~%~v,0Tif can prove: ~A" *indent*Ť‰ (express-instance (Horn-clause-body assertion) new-sub)))))ŤŤ(defun epilogue (goal assertion new-sub proofs)Ť (when new-subŤ (when *trace-prolog*Ť (cond ((null (Horn-clause-body assertion))Ť‰‰‰ (format t "~%~v,0TQ.E.D." *indent*))Ť‰ ((null proofs) (format t "~%~v,0TDRATS!" *indent*))))Ť (do ((ps proofs (rest-of-stream ps))) ((empty-stream-p ps))Ť (if (or *trace-prolog* (zerop *proof-level*))Ť‰(format t "~%~v,0T~A" *indent*Ť‰‰(express-instance goal (next-in-stream ps))))Ť (if (and (zerop *proof-level*) (not (y-or-n-p "More?")))Ť‰(throw 'proofs-of proofs)))))ŤŚŤ;;;;How to FailŤŤŤ(defmacro fail () `nil)Ť(defmacro failed-p (substitution?) `(null ,substitution?))ŤŤ(defun stream-of? (substitution?)Ť (if (not (failed-p substitution?))Ť (stream-of substitution?)Ť (make-empty-stream)))ŤŤŤŤ;;;;Stream-Oriented Theorem ProverŤŤŤ(defun prove (goal assertions substitution)Ť (cond ((null assertions) (stream-of? (fail)))Ť‰((merge-streams (prove-it goal (first assertions) substitution)Ť‰‰‰(prove goal (rest assertions) substitution)))))ŤŤ(defun prove-it (goal assertion substitution)Ť (setq assertion (copy-pattern assertion))Ť (let ((new-subŤ‰ (unifier? goal (Horn-clause-head assertion) substitution)))Ť (with-trace (goal assertion substitution new-sub)Ť (prove-anded-goals (Horn-clause-body assertion) new-sub))))ŤŤ(defun prove-anded-goals (goals substitution?)Ť (cond ((null goals) (stream-of? substitution?))Ť‰((failed-p substitution?) (stream-of? substitution?))Ť‰((prove-anded-goals-in-ored-substitutionsŤ‰‰(rest goals)Ť‰‰(prove (first goals)Ť‰‰ (candidate-assertions (first goals))Ť‰‰ substitution?)))))ŤŤ(defun prove-anded-goals-in-ored-substitutions (goals substitutions)Ť (cond ((or (null goals) (empty-stream-p substitutions)) substitutions)Ť‰((merge-streamsŤ‰ (prove-anded-goals goals (next-in-stream substitutions))Ť‰ (prove-anded-goals-in-ored-substitutionsŤ‰ goals (rest-of-stream substitutions))))))ŤŚŤ;;;;Initial Knowledge BaseŤŤŤ(clear-database)ŤŤ(define-predicate trueŤ ((true)))ŤŤ(define-predicate falseŤ )ŤŤ(define-predicate failŤ )ŤŤ(define-predicate =Ť ((= ?))Ť ((= ?x ?x . ?more) (= ?x . ?more))Ť ((=)))ŤŤ(define-predicate andŤ ((and))Ť ((and ?first . ?rest) ?first (and . ?rest)))ŤŤ(define-predicate orŤ ((or ?first . ?) ?first)Ť ((or ? . ?rest) (or . ?rest)))ŤŤ(define-predicate appendŤ ((append ()))Ť ((append ?x ?x))Ť ((append ?appended () ?y . ?rest)Ť (append ?appended ?y . ?rest))Ť ((append (?x1 . ?u) (?x1 . ?xrest) ?y . ?rest)Ť (append ?u ?xrest ?y . ?rest)))ŤŤ(define-predicate reverseŤ ((reverse ?reversed-so-far () ?reversed-so-far))Ť ((reverse ?reversed (?first . ?rest) ?reversed-so-far)Ť (reverse ?reversed ?rest (?first . ?reversed-so-far)))Ť ((reverse ?reversed ?x) (reverse ?reversed ?x ())))ŤŤ(define-predicate memberŤ ((member ?x (?x . ?)))Ť ((member ?x (? . ?rest)) (member ?x ?rest)))ŤŚŤ(define-predicate successorŤ ((successor 1 0))Ť ((successor 2 1))Ť ((successor 3 2))Ť ((successor 4 3))Ť ((successor 5 4)))ŤŤ(define-predicate <Ť ((< ?x ?y) (successor ?y ?x))Ť ((< ?x ?y) (successor ?y ?y-1) (< ?x ?y-1)))ŤŤ(define-predicate partitionŤ ((partition () () ? ()))Ť ((partition (?first . ?smaller) ?bigger ?key (?first . ?rest))Ť (< ?first ?key)Ť (partition ?smaller ?bigger ?key ?rest))Ť ((partition ?smaller (?first . ?bigger) ?key (?first . ?rest))Ť (or (< ?key ?first) (= ?key ?first))Ť (partition ?smaller ?bigger ?key ?rest)))ŤŤ(define-predicate quick-sortŤ ((quick-sort ?biggest-sorted () ?biggest-sorted))Ť ((quick-sort ?sorted (?key . ?rest) ?biggest-sorted)Ť (partition ?smaller ?bigger ?key ?rest)Ť (quick-sort ?all>=key-sorted ?bigger ?biggest-sorted)Ť (quick-sort ?sorted ?smaller (?key . ?all>=key-sorted)))Ť ((quick-sort ?sorted ?unsorted) (quick-sort ?sorted ?unsorted ())))ŤŤŤ(define-predicate parentŤ ((parent ?p ?c) (mother ?p ?c))Ť ((parent ?p ?c) (father ?p ?c)))ŤŤ(define-predicate grandparentŤ ((grandparent ?grand ?child) (parent ?grand ?par) (parent ?par ?child)))ŤŤ(assert-emŤ ((grandparent gramps babe))Ť ((mother alice george))Ť ((father george peewee)))ŤŤ(define-predicate mortalŤ ((mortal ?being) (human ?being)))ŤŤ(assert-emŤ ((human socrates)))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 17 :LENGTH-IN-BYTES 16754 :AUTHOR "SAM" :CREATION-DATE 2722375354 :QFASLP NIL :LENGTH 16754 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "PROLOG" :TYPE "SESSION" :VERSION 1) ;Reading at top level.Ť;Reading in base 10 in package USER with standard Zetalisp readtable.ŤŤ(login 'sam t)ŤTŤŤ(load "emma:lisp2-ai;prolog-init")ŤLoading PEEL: LISP2-AI; PROLOG-INIT.LISP#> into package USERŤLoading PEEL: LISP2-AI; CL-INIT.QFASL#> into package USERŤŚŤŤŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤŤ___________________________________________________________________________ŤSamuel F. PilatoŤŤŤ Initializing a CommonLisp environment: providing for ...ŤŤ CommonLisp Readtable InitializationŤ Maintaining a Module RegistryŤ Enhancement of REQUIRE Function (REQUIRE being redefined)Ť Ordered Compiling and Loading of ModulesŤŤ CommonLisp initialization is complete.ŤŤ To set *readtable* to a copy of the standard CommonLisp readtable, typeŤ (CL-INIT) .Ť This is undone upon logout.ŤŤ To register a module, typeŤ (REGISTER-MODULE module-name [pathname]) .ŤŤ To retrieve the names of modules currently registered, typeŤ (REGISTERED-MODULES) .ŤŤ To load a registered module -- or for that matter, often even to load aŤ simple UNregistered module -- just typeŤ (REQUIRE ) .ŤŤ Please inspect the source file for further documentation of these andŤ other new facilities.ŤŤLoading PEEL: LISP2-AI; PROLOG.QFASL#> into package USERŤLoading PEEL: LISP2-AI; UNIFICATION.QFASL#> into package USERŤLoading PEEL: LISP2-AI; LIST-PATTERNS.QFASL#> into package USERŤLoading PEEL: LISP2-AI; VARIABLE-SUBSTITUTION.QFASL#> into package USERŤLoading PEEL: LISP2-AI; PREDICATE-CALCULUS.QFASL#> into package USERŤLoading PEEL: LISP2-AI; DEFINING.QFASL#> into package USERŤLoading PEEL: LISP2-AI; PATTERN-PROCESSING.QFASL#> into package USERŤLoading PEEL: LISP2-AI; STREAMS.QFASL#> into package USERŤLoading PEEL: LISP2-AI; HANOI_PROLOG.QFASL#> into package USERŤLoading PEEL: LISP2-AI; OTHER.QFASL#> into package USERŤŤ#FS::LM-PATHNAME "PEEL: LISP2-AI; PROLOG-INIT.LISP#1"ŤŤ(cl-init)Ť;Reading in base 10 in package USER with #.ŤŚŤ(show-unifier-of '(a b c)Ť‰‰ '(a b c))ŤŤ(A B C)Ť(A B C)ŤŤŤ(A B C)Ť(A B C)ŤŤŤŤ(show-unifier-of '(a ?x c ?y e)Ť‰‰ '(a b ?z d e))ŤŤ(A ?X C ?Y E)Ť X[1] = BŤ Y[1] = DŤ(A B C D E)ŤŤŤ(A B ?Z D E)Ť Z[2] = CŤ(A B C D E)ŤŤŤŤ(show-unifier-of '(near Mercedes theatre)Ť‰‰ '(nearby Mercedes theater))ŤnoneŤŤŤŤ(show-unifier-of '(a ?x ?x ?x)Ť‰‰ '(a ?y ?y ?y))ŤŤ(A ?X ?X ?X)Ť X[1] = Y[2]Ť(A Y[2] Y[2] Y[2])ŤŤŤ(A ?Y ?Y ?Y)Ť Y[2]Ť(A Y[2] Y[2] Y[2])ŤŚŤ(show-unifier-of '(a ?x ?x)Ť‰‰ '(a ?y b))ŤŤ(A ?X ?X)Ť X[1] = Y[2]‰ = BŤ(A B B)ŤŤŤ(A ?Y B)Ť Y[2] = BŤ(A B B)ŤŤŤŤ(show-unifier-of '(a ?x ( c ?y))Ť‰‰ '(a (b ?z) (?w ?z)))ŤŤ(A ?X (C ?Y))Ť X[1] = (B Z[2])Ť Y[1] = Z[2]Ť(A (B Z[2]) (C Z[2]))ŤŤŤ(A (B ?Z) (?W ?Z))Ť Z[2]Ť W[2] = CŤ(A (B Z[2]) (C Z[2]))ŤŤŤŤ(show-unifier-ofŤ '(implies (precipitate-on ?precipitate ?object) (wet ?object))Ť '(implies (precipitate-on rain sidewalks) ?consequent))ŤŤ(IMPLIES (PRECIPITATE-ON ?PRECIPITATE ?OBJECT) (WET ?OBJECT))Ť PRECIPITATE[1]‰ = RAINŤ OBJECT[1] = SIDEWALKSŤ(IMPLIES (PRECIPITATE-ON RAIN SIDEWALKS) (WET SIDEWALKS))ŤŤŤ(IMPLIES (PRECIPITATE-ON RAIN SIDEWALKS) ?CONSEQUENT)Ť CONSEQUENT[2]‰ = (WET OBJECT[1])Ť(IMPLIES (PRECIPITATE-ON RAIN SIDEWALKS) (WET SIDEWALKS))ŤŚŤ(show-unifier-of '(a ?x c)Ť‰‰ '(a b e))ŤnoneŤŤŤ(show-unifier-of '(a ?x c ?x e)Ť‰‰ '(a b ?z d e))ŤnoneŤŤŤ(show-unifier-of '(a ?x ?x)Ť‰‰ '(a (b ?y) ?y))ŤnoneŤŤŤ(show-unifier-of '(a ?x ?y)Ť‰‰ '(a (b ?y) ?x))ŤŤ(A ?X ?Y)Ť X[1] = (B Y[2])Ť Y[1] = X[2]Ť(A (B Y[2]) X[2])ŤŤŤ(A (B ?Y) ?X)Ť Y[2]Ť X[2]Ť(A (B Y[2]) X[2])ŤŤŤŤ(let ((both (patternize '((a ?x ?y)Ť‰‰‰ (a (b ?y) ?x)) )))Ť (show-unifier-of (first both) (second both)))ŤnoneŤŤŤŤ(let ((both (patternize '((?x ?y ?z)Ť‰‰‰ (?y ?z ?x)))))Ť (show-unifier-of (first both) (second both)))ŤŤ(?X ?Y ?Z)Ť(Z[NIL] Z[NIL] Z[NIL])ŤŤŤ(?Y ?Z ?X)Ť(Z[NIL] Z[NIL] Z[NIL])ŤŚŤ(show-unifier-of '(?x (?y1 . ?yrest) ?z1 . ?zrest)Ť‰‰ '(a (b c d e f g ) h ))ŤŤ(?X (?Y1 . ?YREST) ?Z1 . ?ZREST)Ť X[1] = AŤ Y1[1] = BŤ YREST[1] = (C D E F G)Ť Z1[1] = HŤ ZREST[1] = NILŤ(A (B C D E F G) H)ŤŤŤ(A (B C D E F G) H)Ť(A (B C D E F G) H)ŤŚŤ(show-unifier-of '(implies ?antecedent (mortal ?who))Ť‰‰ '(implies (human ?x) (mortal ?x )))ŤŤ(IMPLIES ?ANTECEDENT (MORTAL ?WHO))Ť ANTECEDENT[1]‰ = (HUMAN X[2])Ť WHO[1] = X[2]Ť(IMPLIES (HUMAN X[2]) (MORTAL X[2]))ŤŤŤ(IMPLIES (HUMAN ?X) (MORTAL ?X))Ť X[2]Ť(IMPLIES (HUMAN X[2]) (MORTAL X[2]))ŤŤ(show-unifier-of '(human ?x)Ť‰‰ '(human Socrates))ŤŤ(HUMAN ?X)Ť X[1] = SOCRATESŤ(HUMAN SOCRATES)ŤŤŤ(HUMAN SOCRATES)Ť(HUMAN SOCRATES)ŤŤŤŤ(let* ((query (patternize '(mortal ?who)))Ť (rule-in-kb (patternize '(implies (human ?x) (mortal ?x))))Ť (fact-in-kb (patternize '(human Socrates)))ŤŤ (query-variable (second query))Ť (antecedent (patternize '?antecedent))Ť (consequent (patternize '?consequent))Ť (backward-chain-patternŤ‰‰ (patternize `(implies ,antecedent ,consequent))))ŤŤ (setq substitution (unify? backward-chain-pattern rule-in-kb)Ť‰substitution (unify? query consequent substitution)Ť‰substitution (unify? antecedent fact-in-kb substitution))ŤŤ (terpri)Ť (print (express-pattern query))Ť (show-bindings query-variable substitution)Ť (print (express-pattern (instantiate-pattern query substitution t)))Ť (terpri)(values))ŤŤ(MORTAL ?WHO) Ť ?WHO = ?X‰ = SOCRATESŤ(MORTAL SOCRATES) ŤŚŤ(show-database)Ť((HANOI ((MOVE FROM ?X TO ?Y) . ?REV-SO-FAR) ?REV-SO-FAR ?X ?Y ? 1))Ť((HANOI ?REV-SOLUTION ?REV-SO-FAR ?X ?Y ?Z ?N)Ť (SUCCESSOR ?N ?N-1)Ť (HANOI ?S1 ?REV-SO-FAR ?X ?Z ?Y ?N-1)Ť (HANOI ?S2 ?S1 ?X ?Y ?Z 1)Ť (HANOI ?REV-SOLUTION ?S2 ?Z ?Y ?X ?N-1))Ť((HANOI ?SOLUTION ?X ?Y ?Z ?N)Ť (HANOI ?REV-SOLUTION NIL ?X ?Y ?Z ?N)Ť (REVERSE ?SOLUTION ?REV-SOLUTION))Ť((HUMAN SOCRATES))Ť((MORTAL ?BEING) (HUMAN ?BEING))Ť((GRANDPARENT GRAMPS BABE))Ť((MOTHER ALICE GEORGE))Ť((FATHER GEORGE PEEWEE))Ť((GRANDPARENT ?GRAND ?CHILD) (PARENT ?GRAND ?PAR) (PARENT ?PAR ?CHILD))Ť((PARENT ?P ?C) (MOTHER ?P ?C))Ť((PARENT ?P ?C) (FATHER ?P ?C))Ť((QUICK-SORT ?BIGGEST-SORTED NIL ?BIGGEST-SORTED))Ť((QUICK-SORT ?SORTED (?KEY . ?REST) ?BIGGEST-SORTED)Ť (PARTITION ?SMALLER ?BIGGER ?KEY ?REST)Ť (QUICK-SORT ?ALL>=KEY-SORTED ?BIGGER ?BIGGEST-SORTED)Ť (QUICK-SORT ?SORTED ?SMALLER (?KEY . ?ALL>=KEY-SORTED)))Ť((QUICK-SORT ?SORTED ?UNSORTED) (QUICK-SORT ?SORTED ?UNSORTED NIL))Ť((PARTITION NIL NIL ? NIL))Ť((PARTITION (?FIRST . ?SMALLER) ?BIGGER ?KEY (?FIRST . ?REST))Ť (< ?FIRST ?KEY)Ť (PARTITION ?SMALLER ?BIGGER ?KEY ?REST))Ť((PARTITION ?SMALLER (?FIRST . ?BIGGER) ?KEY (?FIRST . ?REST))Ť (OR (< ?KEY ?FIRST) (= ?KEY ?FIRST))Ť (PARTITION ?SMALLER ?BIGGER ?KEY ?REST))Ť((< ?X ?Y) (SUCCESSOR ?Y ?X))Ť((< ?X ?Y) (SUCCESSOR ?Y ?Y-1) (< ?X ?Y-1))Ť((SUCCESSOR 1 0))Ť((SUCCESSOR 2 1))Ť((SUCCESSOR 3 2))Ť((SUCCESSOR 4 3))Ť((SUCCESSOR 5 4))Ť((MEMBER ?X (?X . ?)))Ť((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ť((REVERSE ?REVERSED-SO-FAR NIL ?REVERSED-SO-FAR))Ť((REVERSE ?REVERSED (?FIRST . ?REST) ?REVERSED-SO-FAR)Ť (REVERSE ?REVERSED ?REST (?FIRST . ?REVERSED-SO-FAR)))Ť((REVERSE ?REVERSED ?X) (REVERSE ?REVERSED ?X NIL))Ť((APPEND NIL))Ť((APPEND ?X ?X))Ť((APPEND ?APPENDED NIL ?Y . ?REST)Ť (APPEND ?APPENDED ?Y . ?REST))Ť((APPEND (?X1 . ?U) (?X1 . ?XREST) ?Y . ?REST)Ť (APPEND ?U ?XREST ?Y . ?REST))ŤŚŤ((OR ?FIRST . ?) ?FIRST)Ť((OR ? . ?REST) (OR . ?REST))Ť((AND))Ť((AND ?FIRST . ?REST) ?FIRST (AND . ?REST))Ť((= ?))Ť((= ?X ?X . ?MORE) (= ?X . ?MORE))Ť((=))Ť((TRUE))ŤŚŤ(query (mortal ?who))Ť(MORTAL SOCRATES)ŤMore? (Y or N) Yes.ŤŤŤ(MORTAL ?WHO) Ť ?WHO = ?BEING = SOCRATESŤ(MORTAL SOCRATES) ŤŤŤŤ(query (?what socrates))Ť(HUMAN SOCRATES)ŤMore? (Y or N) Yes.Ť(MORTAL SOCRATES)ŤMore? (Y or N) Yes.Ť(= SOCRATES)ŤMore? (Y or N) Yes.ŤŤŤ(?WHAT SOCRATES) Ť ?WHAT = HUMANŤ(HUMAN SOCRATES) ŤŤŤ(?WHAT SOCRATES) Ť ?WHAT = MORTALŤ(MORTAL SOCRATES) ŤŤŤ(?WHAT SOCRATES) Ť ?WHAT = =Ť(= SOCRATES) ŤŚŤ(query (mortal ?who) t)ŤCan prove: (MORTAL ?WHO) with assertion ((MORTAL ?BEING) (HUMAN ?BEING))Ťif can prove: ((HUMAN ?BEING))Ť Can prove: (HUMAN ?BEING) with assertion ((HUMAN SOCRATES))Ť Q.E.D.Ť (HUMAN SOCRATES)Ť(MORTAL SOCRATES)ŤMore? (Y or N) Yes.ŤŤŤ(MORTAL ?WHO) Ť ?WHO = ?BEING = SOCRATESŤ(MORTAL SOCRATES) ŤŤŤŤ(query (?what socrates) t)ŤCan prove: (?WHAT SOCRATES) with assertion ((HUMAN SOCRATES))ŤQ.E.D.Ť(HUMAN SOCRATES)ŤMore? (Y or N) Yes.ŤCan prove: (?WHAT SOCRATES) with assertion ((MORTAL ?BEING) (HUMAN ?BEING))Ťif can prove: ((HUMAN SOCRATES))Ť Can prove: (HUMAN SOCRATES) with assertion ((HUMAN SOCRATES))Ť Q.E.D.Ť (HUMAN SOCRATES)Ť(MORTAL SOCRATES)ŤMore? (Y or N) No.ŤŤŤ(?WHAT SOCRATES) Ť ?WHAT = MORTALŤ(MORTAL SOCRATES) ŤŚŤ(query (grandparent ?elder ?youth))Ť(GRANDPARENT GRAMPS BABE)ŤMore? (Y or N) Yes.Ť(GRANDPARENT ALICE PEEWEE)ŤMore? (Y or N) Yes.ŤŤŤ(GRANDPARENT ?ELDER ?YOUTH) Ť ?ELDER = GRAMPSŤ ?YOUTH = BABEŤ(GRANDPARENT GRAMPS BABE) ŤŤŤ(GRANDPARENT ?ELDER ?YOUTH) Ť ?ELDER = ?GRAND = ?P‰ = ALICEŤ ?YOUTH = ?CHILD = ?C‰ = PEEWEEŤ(GRANDPARENT ALICE PEEWEE) ŤŤŤŤ(query (?relationship alice george))Ť(MOTHER ALICE GEORGE)ŤMore? (Y or N) Yes.Ť(PARENT ALICE GEORGE)ŤMore? (Y or N) Yes.ŤŤŤ(?RELATIONSHIP ALICE GEORGE) Ť ?RELATIONSHIP‰ = MOTHERŤ(MOTHER ALICE GEORGE) ŤŤŤ(?RELATIONSHIP ALICE GEORGE) Ť ?RELATIONSHIP‰ = PARENTŤ(PARENT ALICE GEORGE) ŤŤŤŤ(query (?relationship alice peewee))Ť(GRANDPARENT ALICE PEEWEE)ŤMore? (Y or N) Yes.ŤŤŤ(?RELATIONSHIP ALICE PEEWEE) Ť ?RELATIONSHIP‰ = GRANDPARENTŤ(GRANDPARENT ALICE PEEWEE) ŤŚŤ(query (grandparent ?elder ?youth) t)ŤCan prove: (GRANDPARENT ?ELDER ?YOUTH) with assertionŤ‰‰‰‰‰((GRANDPARENT GRAMPS BABE))ŤQ.E.D.Ť(GRANDPARENT GRAMPS BABE)ŤMore? (Y or N) Yes.ŤCan prove: (GRANDPARENT ?ELDER ?YOUTH) with assertionŤ‰‰‰‰‰((GRANDPARENT ?GRAND ?CHILD)Ť‰‰‰‰‰ (PARENT ?GRAND ?PAR)Ť‰‰‰‰‰ (PARENT ?PAR ?CHILD))Ťif can prove: ((PARENT ?GRAND ?PAR) (PARENT ?PAR ?CHILD))Ť Can prove: (PARENT ?GRAND ?PAR) with assertionŤ‰‰‰‰ ((PARENT ?P ?C) (MOTHER ?P ?C))Ť if can prove: ((MOTHER ?P ?C))Ť Can prove: (MOTHER ?P ?C) with assertion ((MOTHER ALICE GEORGE))Ť Q.E.D.Ť (MOTHER ALICE GEORGE)Ť (PARENT ALICE GEORGE)Ť Can prove: (PARENT ?GRAND ?PAR) with assertionŤ‰‰‰‰ ((PARENT ?P ?C) (FATHER ?P ?C))Ť if can prove: ((FATHER ?P ?C))Ť Can prove: (FATHER ?P ?C) with assertion ((FATHER GEORGE PEEWEE))Ť Q.E.D.Ť (FATHER GEORGE PEEWEE)Ť (PARENT GEORGE PEEWEE)Ť Can prove: (PARENT GEORGE ?CHILD) with assertionŤ‰‰‰‰ ((PARENT ?P ?C) (MOTHER ?P ?C))Ť if can prove: ((MOTHER GEORGE ?C))Ť DRATS!Ť Can prove: (PARENT GEORGE ?CHILD) with assertionŤ‰‰‰‰ ((PARENT ?P ?C) (FATHER ?P ?C))Ť if can prove: ((FATHER GEORGE ?C))Ť Can prove: (FATHER GEORGE ?C) with assertion ((FATHER GEORGE PEEWEE))Ť Q.E.D.Ť (FATHER GEORGE PEEWEE)Ť (PARENT GEORGE PEEWEE)Ť Can prove: (PARENT PEEWEE ?CHILD) with assertionŤ‰‰‰‰ ((PARENT ?P ?C) (MOTHER ?P ?C))Ť if can prove: ((MOTHER PEEWEE ?C))Ť DRATS!Ť Can prove: (PARENT PEEWEE ?CHILD) with assertionŤ‰‰‰‰ ((PARENT ?P ?C) (FATHER ?P ?C))Ť if can prove: ((FATHER PEEWEE ?C))Ť DRATS!Ť(GRANDPARENT ALICE PEEWEE)ŤMore? (Y or N) No.ŤŤŤ(GRANDPARENT ?ELDER ?YOUTH) Ť ?ELDER = ?GRAND = ?P‰ = ALICEŤ ?YOUTH = ?CHILD = ?C‰ = PEEWEEŤ(GRANDPARENT ALICE PEEWEE) ŤŚŤ(query (member 4 (8 4 2)) t)ŤCan prove: (MEMBER 4 (8 4 2)) with assertionŤ‰‰‰ ((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ťif can prove: ((MEMBER 4 (4 2)))Ť Can prove: (MEMBER 4 (4 2)) with assertion ((MEMBER ?X (?X . ?)))Ť Q.E.D.Ť (MEMBER 4 (4 2))Ť Can prove: (MEMBER 4 (4 2)) with assertionŤ‰‰‰‰((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ť if can prove: ((MEMBER 4 (2)))Ť Can prove: (MEMBER 4 (2)) with assertionŤ‰‰‰‰ ((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ť if can prove: ((MEMBER 4 NIL))Ť DRATS!Ť DRATS!Ť(MEMBER 4 (8 4 2))ŤMore? (Y or N) Yes.ŤŤŤ(MEMBER 4 (8 4 2)) Ť(MEMBER 4 (8 4 2)) ŤŤŤŤ(query (member 3 (8 4 2)) t)ŤCan prove: (MEMBER 3 (8 4 2)) with assertionŤ‰‰‰ ((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ťif can prove: ((MEMBER 3 (4 2)))Ť Can prove: (MEMBER 3 (4 2)) with assertionŤ‰‰‰‰((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ť if can prove: ((MEMBER 3 (2)))Ť Can prove: (MEMBER 3 (2)) with assertionŤ‰‰‰‰ ((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ť if can prove: ((MEMBER 3 NIL))Ť DRATS!Ť DRATS!ŤDRATS!ŤnoneŤŚŤ(query (member ?any (8 4 2)))Ť(MEMBER 8 (8 4 2))ŤMore? (Y or N) Yes.Ť(MEMBER 4 (8 4 2))ŤMore? (Y or N) Yes.Ť(MEMBER 2 (8 4 2))ŤMore? (Y or N) Yes.ŤŤŤ(MEMBER ?ANY (8 4 2)) Ť ?ANY = ?X‰ = 8Ť(MEMBER 8 (8 4 2)) ŤŤŤ(MEMBER ?ANY (8 4 2)) Ť ?ANY = ?X‰ = ?X‰ = 4Ť(MEMBER 4 (8 4 2)) ŤŤŤ(MEMBER ?ANY (8 4 2)) Ť ?ANY = ?X‰ = ?X‰ = ?X = 2Ť(MEMBER 2 (8 4 2)) ŤŤŤŤ(query (member 3 (?a ?b ?c)))Ť(MEMBER 3 (3 ?B ?C))ŤMore? (Y or N) Yes.Ť(MEMBER 3 (?A 3 ?C))ŤMore? (Y or N) Yes.Ť(MEMBER 3 (?A ?B 3))ŤMore? (Y or N) Yes.ŤŤŤ(MEMBER 3 (?A ?B ?C)) Ť ?A‰ = 3Ť ?BŤ ?CŤ(MEMBER 3 (3 ?B ?C)) ŤŤŤ(MEMBER 3 (?A ?B ?C)) Ť ?A‰ = ?Ť ?B‰ = 3Ť ?CŤ(MEMBER 3 (?A 3 ?C)) ŤŤŤ(MEMBER 3 (?A ?B ?C)) Ť ?A‰ = ?Ť ?B‰ = ?Ť ?C‰ = 3Ť(MEMBER 3 (?A ?B 3)) ŤŚŤ(query (member 3 ?any) t)ŤCan prove: (MEMBER 3 ?ANY) with assertion ((MEMBER ?X (?X . ?)))ŤQ.E.D.Ť(MEMBER 3 (3 . ?))ŤMore? (Y or N) Yes.ŤCan prove: (MEMBER 3 ?ANY) with assertionŤ‰‰‰ ((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ťif can prove: ((MEMBER 3 ?REST))Ť Can prove: (MEMBER 3 ?REST) with assertion ((MEMBER ?X (?X . ?)))Ť Q.E.D.Ť (MEMBER 3 (3 . ?))Ť Can prove: (MEMBER 3 ?REST) with assertionŤ‰‰‰‰((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ť if can prove: ((MEMBER 3 ?REST))Ť Can prove: (MEMBER 3 ?REST) with assertion ((MEMBER ?X (?X . ?)))Ť Q.E.D.Ť (MEMBER 3 (3 . ?))Ť Can prove: (MEMBER 3 ?REST) with assertionŤ‰‰‰‰ ((MEMBER ?X (? . ?REST)) (MEMBER ?X ?REST))Ť if can prove: ((MEMBER 3 ?REST)) . . .ŤŤ; [aborted]ŤŤ;Back to top level.ŤŚŤ(query (append ?result (a b) (c)) t)ŤCan prove: (APPEND ?RESULT (A B) (C)) with assertionŤ‰‰‰‰ ((APPENDŤ‰‰‰‰‰ (?X1 . ?U)Ť‰‰‰‰‰ (?X1 . ?XREST) ?Y . ?REST)Ť‰‰‰‰‰(APPEND ?U ?XREST ?Y . ?REST))Ťif can prove: ((APPEND ?U (B) (C)))Ť Can prove: (APPEND ?U (B) (C)) with assertionŤ‰‰‰‰ ((APPENDŤ‰‰‰‰ (?X1 . ?U)Ť‰‰‰‰ (?X1 . ?XREST) ?Y . ?REST)Ť‰‰‰‰ (APPEND ?U ?XREST ?Y . ?REST))Ť if can prove: ((APPEND ?U NIL (C)))Ť Can prove: (APPEND ?U NIL (C)) with assertionŤ‰‰‰‰ ((APPEND ?APPENDED NIL ?Y . ?REST)Ť‰‰‰‰ (APPEND ?APPENDED ?Y . ?REST))Ť if can prove: ((APPEND ?APPENDED (C)))Ť‰ Can prove: (APPEND ?APPENDED (C)) with assertion ((APPEND ?X ?X))Ť‰ Q.E.D.Ť‰ (APPEND (C) (C))Ť (APPEND (C) NIL (C))Ť (APPEND (B C) (B) (C))Ť(APPEND (A B C) (A B) (C))ŤMore? (Y or N) Yes.ŤŤŤ(APPEND ?RESULT (A B) (C)) Ť ?RESULT = (?X1 . ?U)Ť(APPEND (A B C) (A B) (C)) ŤŤŤŤ(query (append (a b c) (a b) ?what))Ť(APPEND (A B C) (A B) (C))ŤMore? (Y or N) Yes.ŤŤŤ(APPEND (A B C) (A B) ?WHAT) Ť ?WHAT = ?Y‰ = ?Y‰ = ?Y = (C)Ť(APPEND (A B C) (A B) (C)) ŤŤŤŤ(query (append (a b c) ?what (c)))Ť(APPEND (A B C) (A B) (C))ŤMore? (Y or N) Yes.ŤŤŤ(APPEND (A B C) ?WHAT (C)) Ť ?WHAT = (?X1 . ?XREST)Ť(APPEND (A B C) (A B) (C)) ŤŚŤ(query (hanoi ?solution a b c 1))Ť(HANOI ((MOVE FROM A TO B)) A B C 1)ŤMore? (Y or N) Yes.ŤŤŤ(HANOI ?SOLUTION A B C 1) Ť ?SOLUTION = ?SOLUTION‰ = ?REVERSED‰ = ?REVERSEDŤ‰‰= ?REVERSED-SO-FAR = (?FIRST . ?REVERSED-SO-FAR)Ť(HANOI ((MOVE FROM A TO B)) A B C 1) ŤŤŤ(query (hanoi ?solution peg-a peg-b peg-c 4))Ť(HANOI ((MOVE FROM PEG-A TO PEG-C)Ť‰(MOVE FROM PEG-A TO PEG-B)Ť‰(MOVE FROM PEG-C TO PEG-B)Ť‰(MOVE FROM PEG-A TO PEG-C)Ť‰(MOVE FROM PEG-B TO PEG-A)Ť‰(MOVE FROM PEG-B TO PEG-C)Ť‰(MOVE FROM PEG-A TO PEG-C)Ť‰(MOVE FROM PEG-A TO PEG-B)Ť‰(MOVE FROM PEG-C TO PEG-B)Ť‰(MOVE FROM PEG-C TO PEG-A)Ť‰(MOVE FROM PEG-B TO PEG-A)Ť‰(MOVE FROM PEG-C TO PEG-B)Ť‰(MOVE FROM PEG-A TO PEG-C)Ť‰(MOVE FROM PEG-A TO PEG-B)Ť‰(MOVE FROM PEG-C TO PEG-B))Ť PEG-AŤ PEG-BŤ PEG-CŤ 4)ŤMore? (Y or N) Yes.ŤŤŤ(HANOI ?SOLUTION PEG-A PEG-B PEG-C 4) Ť ?SOLUTION = ?SOLUTION = ?REVERSED = ?REVERSED . . .Ť‰‰= ?REVERSED-SO-FAR = (?FIRST . ?REVERSED-SO-FAR)Ť(HANOI ((MOVE FROM PEG-A TO PEG-C)Ť‰. . .Ť‰(MOVE FROM PEG-C TO PEG-B))Ť PEG-AŤ PEG-BŤ PEG-CŤ 4)ŤŤ(logout)ŤTŤ;Reading in base 10 in package USER with standard Zetalisp readtable.ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 1 :LENGTH-IN-BYTES 724 :AUTHOR "SAM" :CREATION-DATE 2725553148 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "PROLOG-INIT" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;PROLOG-INITŤŤ(require 'cl-init "duke:lisp2-circulation;cl-init")ŤŤŤ(with-module-pathname-defaults ("duke: lisp2-circulation;")Ť (apply #'register-modulesŤ‰ '(Ť‰ definingŤ‰ streamsŤ‰ variable-substitutionŤ‰ list-patternsŤ‰ (pattern-definition list-patterns)Ť‰ pattern-processingŤ‰ unificationŤ‰ predicate-calculusŤ‰ PrologŤ‰ Hanoi_PrologŤ‰ otherŤ‰ )))ŤŤ;(compile-load-modules)ŤŤ(require 'Prolog)Ť(require 'Hanoi_Prolog)Ť(require 'other)ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 3 :LENGTH-IN-BYTES 2802 :AUTHOR "wilde" :CREATION-DATE 2716346322 :QFASLP NIL :LENGTH 2802 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "QUERIES" :TYPE "LISP" :VERSION 2) ; -*- mode: lisp ; fonts: (medfnb) ;ibase: 10.;base:10. -*-ŤŤ; a quick testŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ(defun quiz ()Ť (cond ((not (y-or-n-p "Are you ready to start?")) nil)Ť‰(t (run-quiz))))ŤŤ; Getting info from the userŤ(defunp run-quiz (&aux name ans)Ť ;prompt and read is a simple to use function (p. 385)Ť (setq name (prompt-and-read ':string "~%What is your name? "))Ť ; a little more interesting use of prompt and readŤ (quest-satisfied)Ť ; now let's explore using FQUERY Ť (format t "~% Here are some questions for you: ")Ť ; first, we use it in a simple wayŤ (setq ans Ť (fqueryŤ '(:type :readlineŤ :choices ((nil "Blue")(nil "Red")(nil "other")(t "I don't know")))Ť "What is your favorite color?"))Ť (cond (ans (Format t "~% aaaaagggghhhh (it appears you've been killed")Ť‰ (return 'dead))) ;EXIT FROM FUNCTION!!Ť ; a little more complex choice listŤ (setq ansŤ (fqueryŤ '(:type :tyi ;this would be the default, I'm making it explicit Ť :choicesŤ (((t "choice 1") #/a #/1)Ť‰ ((t "choice 2") #/b #/2)Ť‰ ((nil "choice 3") #/c #/3)))Ť " Where are Lisp machines made:Ť a) MassachusettsŤ b) The West CoastŤ c) They are not made, they are born.~%"))Ť (cond (ans (Format t "~% Gotcha on that one -- correct answer was cŤ ~% (appears you are dead)")Ť‰ (return 'Dead))) ;EXIT FROM FUNCTION!!Ť ;using the optionŤ (setq ansŤ (fqueryŤ '(:type :tyiŤ :list-choices nil ;don't list the choicesŤ :help-function quiz-help-functionŤ :choicesŤ (((nil 1) #/1)((nil 2) #/2)((correct 3) #/3)((joke 4) #/4)))Ť "Who was the first president (Hit HELP key for more info):Ť 1) Lincoln 2) JeffersonŤ 3) Washington 4) Hendler~%"))Ť (cond ((not ans)(format t "~% sorry (appears you flunk)")Ť‰‰ (return 'Flunk)) ;EXIT FROM FUNCTIONŤ‰((eq ans 'correct)(format t "Close enough -- you pass")Ť‰‰‰ (return 'Pass));EXIT FROM FUNCTIONŤ‰((eq ans 'joke)(format t "~%Flattery will get you everywhere")Ť‰‰ (return 'WIN))) ;EXIT FROM FUNCTIONŤ) ŤŤ(defun quest-satisfied (&aux response)Ť (setq responseŤ (prompt-and-read ':eval-sexp-or-endŤ‰ ‰ "~%What is your quest?(Enter a lisp form to evaluate) "))Ť (cond ((not response)Ť‰ (format t "~% aww - you gotta have some quest")Ť‰ (quest-satisfied))Ť‰((memq response '(find-grail find-the-grail find-the-holy-grail))Ť‰ (format t "'~% This ain't Monty Python -- try again")Ť‰ (quest-satisfied))Ť‰(t "That's a nice quest")))ŤŤ(defun quiz-help-function (stream &rest ignore)Ť (format streamŤ‰ "~%This is a serious question pertaining to American history.")Ť (format streamŤ "~% (However, feel free to answer flippantly)"))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 4 :LENGTH-IN-BYTES 3535 :AUTHOR "ESMITH" :CREATION-DATE 2685049776 :QFASLP NIL :LENGTH 3535 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "QUICK-STATS" :TYPE "LISP" :VERSION 9) (DEFMACRO DEFAULT-USER-NAME ()Ť `(READ-FROM-STRINGŤ (%P-CONTENTS-OFFSET (CDAR *DEFAULT-PATHNAME-DEFAULTS*) 3)))ŤŤ(DEFMACRO DEFAULT-USER-HOST ()Ť `(%P-CONTENTS-OFFSET (CDAR (LAST *DEFAULT-PATHNAME-DEFAULTS*)) 1))ŤŤ(DEFMACRO MAKE-COPIES-OF (S-EXPR COUNT)Ť `(MAKE-SEQUENCE 'LIST ,COUNT :INITIAL-ELEMENT ,S-EXPR))ŤŤ(DEFSUBST INTERLEAVE (LIST-A LIST-B)Ť (LET* ((LEN-A (LENGTH LIST-A))Ť‰ (LEN-B (LENGTH LIST-B))Ť‰ (TWIST (> LEN-A LEN-B)) ;;; clockwise or counterclockwiseŤ‰ (REMAINDER (IF TWISTŤ‰‰‰(NTHCDR LEN-B LIST-A)Ť‰‰ (NTHCDR LEN-A LIST-B)))Ť‰ (NESTED-LIST-B (MAPCAR 'CONSŤ‰‰‰‰LIST-BŤ‰‰‰‰(MAKE-COPIES-OF 'NIL (IF TWISTŤ‰‰‰‰‰‰‰ LEN-BŤ‰‰‰‰‰‰ LEN-A))))Ť‰ (ADJUSTED-LIST-A (IF TWISTŤ‰‰‰ LIST-AŤ‰‰‰ (FIRSTN LEN-B LIST-A)))Ť‰ (PAIRS-LIST (MAPCAR 'CONS ADJUSTED-LIST-A NESTED-LIST-B))Ť‰ (ANSWER (LOOP FOR ENTRY IN PAIRS-LISTŤ‰‰ WITH RESULT DOŤ‰‰ (SETQ RESULT (APPEND RESULT ENTRY))Ť‰‰ FINALLY (RETURN RESULT))))Ť (APPEND ANSWER REMAINDER)))ŤŤ(DEFMACRO READ-NAME (I)Ť `(PROGN (FORMAT T "~%name ~S> " ,I)Ť‰ (READ-DELIMITED-STRING '(#\END #\RETURN #\LINEFEED))))ŤŤ(DEFMACRO READ-SCORE (I)Ť `(PROGN (FORMAT T "~%score ~S> " ,I)Ť‰ (READ)))ŤŤ(DEFUN ENTER-SCORES ()Ť (FORMAT T "~%To terminate name strings, use END, RETURN or LINEFEED")Ť (FORMAT T "~%SPACE may also be used to terminate scores (but not name strings)")Ť (LET* ((USER-INPUT (DO* ((I 1 (1+ I))Ť‰‰‰ (CURRENT-NAME (READ-NAME I) (READ-NAME I))Ť‰‰‰ (ESCAPE-STRING (STRING-UPCASE CURRENT-NAME)Ť‰‰‰‰‰ (STRING-UPCASE CURRENT-NAME))Ť‰‰‰ (TERMINATION-CONDITIONŤ‰‰‰ (OR (EQUAL ESCAPE-STRING "BYE")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "END")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "EXIT")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "QUIT")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "STOP"))Ť‰‰‰ (OR (EQUAL ESCAPE-STRING "BYE")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "END")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "EXIT")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "QUIT")Ť‰‰‰‰ (EQUAL ESCAPE-STRING "STOP")))Ť‰‰‰ (CURRENT-SCORE (READ-SCORE I)Ť‰‰‰‰‰ (IF TERMINATION-CONDITIONŤ‰‰‰‰‰ -1Ť‰‰‰‰‰ (READ-SCORE I)))Ť‰‰‰ (TERMINATION-CONDITION (OR TERMINATION-CONDITIONŤ‰‰‰‰‰‰ (< CURRENT-SCORE 0))Ť‰‰‰‰‰‰ (OR TERMINATION-CONDITIONŤ‰‰‰‰‰‰ (< CURRENT-SCORE 0)))Ť‰‰‰ (NAMES (LIST CURRENT-NAME)Ť‰‰‰‰ (APPEND NAMES (LIST CURRENT-NAME)))Ť‰‰‰ (SCORES (LIST CURRENT-SCORE)Ť‰‰‰‰ (APPEND SCORES (LIST CURRENT-SCORE))))Ť‰‰‰ (TERMINATION-CONDITIONŤ‰‰‰ (LIST NAMES SCORES)))))Ť USER-INPUT))Ť‰ Ť(DEFVAR ANALYSED-SCORES '(0 0))ŤŤ(DECLARE (SPECIAL ANALYSED-SCORES))ŤŤ(DEFUN ANALYSE-SCORES ()Ť (LET* ((INPUT (ENTER-SCORES))Ť‰ (NAMES (BUTLAST (CAR INPUT)))Ť‰ (SCORES (MAPCAR 'FLOAT (BUTLAST (CADR INPUT))))Ť‰ (N (LENGTH SCORES))Ť‰ (GRAND-TOTAL (APPLY 'PLUS SCORES))Ť‰ (MEAN (QUOTIENT (APPLY 'PLUS SCORES) N))Ť‰ (STD-DEV (SQRTŤ‰‰ (QUOTIENT (APPLY 'PLUSŤ‰‰‰‰ (LET ((MEAN-DIFFSŤ‰‰‰‰‰ (MAPCAR 'DIFFERENCEŤ‰‰‰‰‰‰ (MAKE-COPIES-OF MEAN N)Ť‰‰‰‰‰‰ SCORES)))Ť‰‰‰‰ (MAPCAR 'TIMESŤ‰‰‰‰‰ MEAN-DIFFSŤ‰‰‰‰‰ MEAN-DIFFS)))Ť‰‰‰ N)))Ť‰ (DTSTRING (FORMAT NIL "~\datime\"))Ť‰ (DATESTRING (SUBSTRING DTSTRING 0 (STRING-SEARCH " " DTSTRING)))Ť‰ (QS-FILENAME (STRING-APPEND (DEFAULT-USER-HOST) ": "Ť‰‰‰(DEFAULT-USER-NAME) "; QS-SCORES-"Ť‰‰‰DATESTRINGŤ‰‰‰".TEXT")))Ť (WITH-OPEN-FILE (TERMINAL-IO QS-FILENAME :DIRECTION :OUTPUT)Ť (LOOP FOR ENTRY-PAIR ON (INTERLEAVE NAMES SCORES) BY 'CDDR DOŤ‰ (FORMAT T "~%~S ~S" (CAR ENTRY-PAIR) (CADR ENTRY-PAIR)))Ť (FORMAT T "~%~%Mean: ~S, Standard Deviation: ~S" MEAN STD-DEV))Ť (VIEWF QS-FILENAME)Ť (SETQ ANALYSED-SCORES (LIST MEAN STD-DEV))))ŤŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 23 :LENGTH-IN-BYTES 23464 :AUTHOR "ESMITH" :CREATION-DATE 2695333713 :QFASLP NIL :LENGTH 23464 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "RAPID-PROTOTYPING" :TYPE "LISP" :VERSION 7) ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 1ŤŤŤ;;; -*- Mode:LISP; Package:USER; Fonts:(CPTFONT) -*-ŤŤ;;; Developed by Linda M. ChurchmanŤ;;; Revised by J. Elliott SmithŤ;;; Copyright (C) Lisp Machine Inc. 1984, 1985ŤŤŤ;;; This exercise is a demonstration of rapid software developmentŤ;;; using ZetaLISP on an LMI Lambda LISP Machine.ŤŤŤ;;; To begin our rapid prototyping example, let's draw a few itemsŤ;;; on a window. Our first attempt draws several instances of oneŤ;;; type of graphic figure. We can do this by writing a function Ť;;; that uses a DO {loop} form to request graphics operations thatŤ;;; draw circles on a specified window. *TERMINAL-IO* is a globalŤ;;; variable that the LISP system binds to the input/output streamŤ;;; associated with the currently selected window.ŤŤŤ;;; After we see whether this function works, we can easily thinkŤ;;; of other more interesting things to have it do.ŤŤŤ;;; This exercise assumes that you start in a LISP Listener window.Ť;;; If you are already in an editor buffer, ignore the beginningŤ;;; instructions and start by typing the function into the buffer.ŤŤ;;; Log in by typing Ť;;;Ť;;; (LOGIN 'your-login-name T)Ť;;;Ť;;; and switch to an Editor Buffer by typing -E.Ť;;;Ť;;; When entering a function, the left parenthesis which delimitsŤ;;; the function should be in the column zero. Type each line asŤ;;; shown below. To get automatic indentation of succeeding lines,Ť;;; depress the key at the end of each typed line. If youŤ;;; forget to do that, and type instead, don't panic; theŤ;;; key repositions the cursor on the current line.ŤŤŤ;;; As you are typing, you can move the TEXT cursor from place toŤ;;; place on the screen by positioning the MOUSE cursor where you Ť;;; want to go, and clicking left once.ŤŤŤ;;; NOTE: This exercise performs better if "MORE Processing" isŤ;;; disabled before you start. If it isn't, drawing on the windowŤ;;; will stop whenever the randomly selected graphics cursor comesŤ;;; too near the bottom of the window. The LISP system will waitŤ;;; for you to type a space before continuing.ŤŤ;;; To turn off "MORE Processing", type -1 MŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 2ŤŤŤ;;; Next, to the editor, type in the following function:ŤŤŤ(DEFUN DRF ()Ť (SEND *TERMINAL-IO* ':CLEAR-SCREEN)Ť (DOTIMES (I 10)Ť (SEND *TERMINAL-IO* ':DRAW-CIRCLEŤ‰ (RANDOM 600)Ť‰ (RANDOM 700)Ť‰ (RANDOM 100))))ŤŤŤ;;; As you type, depress the key to terminate each line,Ť;;; instead of the key, and the ZMACS editor will indentŤ;;; your function properly. ZMACS also checks whether parenthesesŤ;;; are balanced {matched}. You can visually confirm that parensŤ;;; are correctly nested by looking for a blinking left paren eachŤ;;; time you type a right parenthesis. {In fact, the correspondingŤ;;; paren blinks whenever the text cursor is directly to the rightŤ;;; of any existing right parenthesis.}ŤŤŤ;;; With the cursor positioned inside of or immmediately after the Ť;;; function you have just entered, type either Control-Shift-C orŤ;;; Hyper-Control-C to compile the function. The two commands areŤ;;; equivalent, and have identical effect {both are implemented byŤ;;; a call to COM-COMPILE-REGION.} If typed exactly as above, theŤ;;; function will compile properly.ŤŤ;;; After the function is compiled, a confirmation message appearsŤ;;; in the "mini-buffer" area at the bottom of the buffer window.Ť;;; Also, while the function is being compiled, the message on theŤ;;; center bottom of the screen says Run instead of Keyboard.ŤŤŤ;;; Return to the LISP Listener by typing - L and test yourŤ;;; function by entering:ŤŤŤ(DRF)ŤŤŚ;;;  LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 3ŤŤŤ;;; Our first attempt works, but it isn't very interesting. Also,Ť;;; it is annoying to have to change windows each time we want toŤ;;; try a new version of the function, so we will change the sizeŤ;;; of the editor buffer, and then create another LISP Listener inŤ;;; a separate another window on the same display.ŤŤŤ;;; The following instructions explain how to restructure an editorŤ;;; buffer, and create a LISP Listener above it.ŤŤ;;; Click double-right on the mouse to obtain the system menu.ŤŤ;;; Clicking left on Edit Screen gets another menu of things to do. ŤŤ;;; A left click left on Reshape causes a cross-in-a-circle mouseŤ;;; cursor to appear. It is used to select the window to reshape.Ť;;; Click left to choose the current editor buffer.ŤŤ;;; Look in the top left corner of the editor for the mouse cursorŤ;;; in the shape of a left corner.ŤŤ;;; Move the mouse cursor about 3/4 of the way down the screen, onŤ;;; the left, and click left.ŤŤ;;; Now look at the bottom right edge of the editor buffer. A rightŤ;;; bottom corner mouse cursor should be there. Leave it where itŤ;;; is, and click right.ŤŤ;;; Your editor buffer should now reshape, and the Edit Screen menuŤ;;; will reappear.ŤŤ;;; Click left on Create to obtain a menu of window types.ŤŤ;;; Click left on Lisp; the mouse cursor again becomes a left corner.ŤŤ;;; Move the corner to the top left of the screen, and click right.ŤŤ;;; Look in the bottom right corner of the screen for a right cornerŤ;;; mouse cursor. Move it just above and to the right of the ZMACSŤ;;; window. Click right.ŤŤ;;; A LISP Listener window forms, and the Edit Screen menu reappears.ŤŤ;;; Click left on Exit. The menu will go away.ŤŤ;;; Click left on the editor buffer to get the function to redisplay.ŤŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 4ŤŤŤ;;; Another way to create a working window setup uses facilitiesŤ;;; available through the system menu. In a LISP Listener, clickŤ;;; right to get the system menu. Click left in the system menu,Ť;;; on "Split Screen" {under "Windows}. This gives you a menu inŤ;;; which you can select kinds of windows to include in your splitŤ;;; screen. ŤŤ;;; Click successively on "Lisp", "Edit", and "Do it".ŤŤ;;; To save this configuration, click right for a system menu, andŤ;;; then click left on "Layouts". You will get a menu which givesŤ;;; you at least two choices. ŤŤ;;; If you click left on "Save This", you will be asked for a nameŤ;;; to reference the screen configuration. The configuration willŤ;;; be bound to a system key if a single character is entered; forŤ;;; example, if you use, say, 9, you can access that configurationŤ;;; by typing -9. After you name a configuration, you can Ť;;; also access it through the system menu, by clicking left onŤ;;; "Layouts", then clicking left on the symbol you supplied.ŤŤŤŤ;;; Now, with the editor buffer on the bottom of the screen, and aŤ;;; LISP Listener on the top of the screen, development continues.Ť;;; Change the function in the editor, compile it, then test it inŤ;;; LISP Listener. Subsequent program development can in this wayŤ;;; proceed quickly and naturally.ŤŤ;;; To improve the function, let's change it to continue drawingŤ;;; figures indefinitely until you type a character on the terminal.Ť;;; The way to do that is to change the DOTIMES to a DO {loop} formŤ;;; that keeps on going until you type on the keyboard. Note thatŤ;;; in order to stop this function, you must type on the keyboardŤ;;; while the LISP Listener has control, so that the character goesŤ;;; into the Lisp listener's input buffer. Change the function to Ť;;; look as follows {the change is on the third line}:ŤŤ(DEFUN DRF ()Ť (SEND *TERMINAL-IO* ':CLEAR-SCREEN)Ť (DO () ((SEND *TERMINAL-IO* ':TYI-NO-HANG) 'DONE)Ť (SEND *TERMINAL-IO* ':DRAW-CIRCLEŤ‰ (RANDOM 600)Ť‰ (RANDOM 700)Ť‰ (RANDOM 100))))ŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 5ŤŤŤ;;; After you compile the changed function with Control-Shift-C,Ť;;; test it by moving the mouse cursor to the LISP Listener at theŤ;;; top of the screen, clicking left, and typing Control-C to makeŤ;;; the function reappear. Note that the final right parenthesis Ť;;; is already there. To evaluate the function, enter a carriageŤ;;; return, or hit , and re-enter the closing ")".ŤŤŤ;;; The function now looks better, so let's develop it further.ŤŤŤ;;; Click left on the editor buffer to transfer control. Each timeŤ;;; you transfer between ZMACS and the LISP Listener, you have toŤ;;; click left on the window you are transferring to. I assume inŤ;;; the remainder of these instructions that you have done so when Ť;;; necessary.ŤŤŤ;;; It would be nice to specify which window to do the drawing in.ŤŤ;;; We can do this by typingŤŤ;;; -X,ŤŤ;;; then {to a mini-buffer} the words "Replace String" {withoutŤ;;; the double quotes}, followed by a carriage return.ŤŤ;;; Next, enter "*TERMINAL-IO*" followed with a carriage return,Ť;;; then "W" followed by a carriage return.ŤŤ;;; The other thing we need to do is specify that W be a parameterŤ;;; of our function. To do this, insert W within the parentheses,Ť;;; (), that follow the function name.ŤŤŤ;;; We also want to be able to specify an area to draw the figuresŤ;;; based on the size of the window we are putting them in, ratherŤ;;; than explicitly specifying the numbers. To do this, define twoŤ;;; local variables MAX-X-SIZE and MAX-Y-SIZE inside a let, thenŤ;;; substitute MAX-X-SIZE and MAX-Y-SIZE for the constants "600" &Ť;;; "700", respectively. As you can see, we've inserted three newŤ;;; lines after the first, changed the second and third lines fromŤ;;; the bottom, and added a right parenthesis on the last line.ŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 6ŤŤŤ;;; When you are making changes to a function that may change itsŤ;;; proper indentation, it is important to check the new indenting Ť;;; to see if the results are what you intended. ŤŤ;;; With the cursor inside the function you want to check, typeŤ;;; Control-Meta-H to mark it as a region, which is underlinedŤ;;; along with any text {comments} immediately preceeding it. ThenŤ;;; type Control-Meta-\ to re-indent the entire function.ŤŤ;;; Use this technique whenever necessary as you make changes.Ť Ť(DEFUN DRF (W)Ť (SEND W ':CLEAR-SCREEN)Ť (LET ((MAX-X-SIZE (SEND W ':INSIDE-WIDTH))Ť‰(MAX-Y-SIZE (SEND W ':INSIDE-HEIGHT)))Ť (DO () ((SEND W ':TYI-NO-HANG) 'DONE)Ť (SEND W ':DRAW-CIRCLEŤ‰ (RANDOM MAX-X-SIZE)Ť‰ (RANDOM MAX-Y-SIZE)Ť‰ (RANDOM 100)))))ŤŤ;;; Compile and test again as above. But wait, we have an error,Ť;;; which informs us that we have only zero arguments. What did weŤ;;; forget? Maybe the debugger will help us.ŤŤ;;; When asked if you want to enter the debugger, answer by typingŤ;;; the single letter Y. This tells us that we needed to specify Ť;;; the new parameter W, the window in which we wish to draw. TheŤ;;; debugger gives us the option of resuming function executionŤ;;; {type the following things to the prompt arrow}:ŤŤ;;; {on the upper right of the keyboard}, thenŤ;;; *TERMINAL-IO*, followed by a carriage return.ŤŤ;;; If you decide to use the window based debugger to gain furtherŤ;;; insight into the problem, type Control-Meta-W, which producesŤ;;; the window based debugger screen.ŤŤ;;; Quoting from the Window System Manual, page 171:ŤŤ;;; "The debugger window is divided into six panes. At the Ť;;; bottom is a Lisp-listener-like window, which ordinarily Ť;;; provides a read-eval-print-loop similar to the regular Ť;;; keyboard debugger.... ŤŤ;;; "At the top is a display of the disassembled or ground Ť;;; code for the currently selected stack frame.... ŤŤ;;; "It has a scroll-bar....ŤŤ;;; "Next are the args and locals windows, side by side, Ť;;; displaying the names and values of the arguments to the Ť;;; current stack frame and its local variables....ŤŤ;;; "Next is the stack window, which displays in a pseudo-list Ť;;; format the functions and arguments on the stack....Ť;;; Below this, and above the Lisp window, is the command Ť;;; menu for the debugger window...."ŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 7ŤŤŤ;;; Put the mouse cursor on Proceed, and click left. You will be Ť;;; asked to supply a value for the variable w. Type *TERMINAL-IO*Ť;;; and a , then just wait. The window based debugger will Ť;;; exit to the LISP Listener and then execute the function {whichŤ;;; should work this time}.ŤŤŤŤ;;; The latest results are much better, reminiscent of New Year'sŤ;;; Eve, but the display is getting a little busy, so let's clearŤ;;; the screen periodically, and write a string on the window. WeŤ;;; want the capability to do either circles or repetitions of aŤ;;; string. The changes are on the first line, the line after theŤ;;; DO form, and another 2 lines at the end of the function. ThereŤ;;; should be 3 right parentheses on the right side of the latestŤ;;; addition.ŤŤ;;; Notice the optional arguments:ŤŤ;;; (DRF *TERMINAL-IO*) draws both circles and the string "Linda"Ť;;; on the current Lisp listener;ŤŤ;;; (DRF *TERMINAL-IO* T NIL) draws just circles;ŤŤ;;; (DRF *TERMINAL-IO* NIL T) draws just the string "Linda";ŤŤ;;; (DRF *TERMINAL-IO* T T "George") draws circles and the stringŤ;;; "George"; and so on.ŤŤ;;; Try different combinations while practising to see what happens.ŤŤŤ;;; The function now looks as follows: ŤŤ(DEFUN DRFŤ (W &OPTIONAL (DRAW-CIRCLES T) (DRAW-STRINGS T)Ť‰(OUT-STRING "LINDA"))Ť (SEND W ':CLEAR-SCREEN)Ť (LET ((MAX-X-SIZE (SEND W ':INSIDE-WIDTH))Ť‰(MAX-Y-SIZE (SEND W ':INSIDE-HEIGHT)))Ť (DO () ((SEND W ':TYI-NO-HANG) 'DONE)Ť (WHEN (< (RANDOM 100) 1) (SEND W ':CLEAR-SCREEN))Ť (WHEN DRAW-CIRCLESŤ‰(SEND W ':DRAW-CIRCLEŤ‰ (RANDOM MAX-X-SIZE)Ť‰ (RANDOM MAX-Y-SIZE)Ť‰ (RANDOM 100)))Ť (WHEN DRAW-STRINGSŤ‰(SEND W ':STRING-OUT OUT-STRING))Ť‰)))ŤŤ;;; Again, compile the function. This time, to test it, type theŤ;;; entire function call to the Lisp listener, as follows:ŤŤ(DRF *TERMINAL-IO*)ŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 8ŤŤŤ;;; That's interesting, but let's make the string jump around onŤ;;; the screen, too. We can do so by changing the cursor positionŤ;;; each time we print the string. Let's also print the stringŤ;;; in a larger font. Add two lines after the second line in theŤ;;; function. Add three new lines directly after the statementŤ;;; "(when draw-strings".Ť Ť;;; Now the function looks like this:ŤŤ(DEFUN DRFŤ (W &OPTIONAL (DRAW-CIRCLES T) (DRAW-STRINGS T)Ť‰(OUT-STRING "LINDA"))Ť (SEND W ':CLEAR-SCREEN)Ť (SEND W ':SET-FONT-MAP '(FONTS:BIGFNT FONTS:CPTFONT))Ť (SEND W ':SET-CURRENT-FONT 'FONTS:BIGFNT)Ť (LET ((MAX-X-SIZE (SEND W ':INSIDE-WIDTH))Ť‰(MAX-Y-SIZE (SEND W ':INSIDE-HEIGHT)))Ť (DO () ((SEND W ':TYI-NO-HANG) 'DONE)Ť (WHEN (< (RANDOM 100) 1) (SEND W ':CLEAR-SCREEN))Ť (WHEN DRAW-CIRCLESŤ‰(SEND W ':DRAW-CIRCLEŤ‰ (RANDOM MAX-X-SIZE)Ť‰ (RANDOM MAX-Y-SIZE)Ť‰ (RANDOM 100)))Ť (WHEN DRAW-STRINGSŤ‰(SEND W ':SET-CURSORPOSŤ‰ (RANDOM MAX-X-SIZE)Ť‰ (RANDOM MAX-Y-SIZE))Ť‰(SEND W ':STRING-OUT OUT-STRING))Ť‰)))ŤŤ;;; Compile {hit Hyper-Control-C} and test again {hit Control-C Ť;;; in the LISP Listener}.ŤŤŤ;;; That is much more interesting. The function is getting a bitŤ;;; large however, so let's separate it into three functions, andŤ;;; make the "done" appear at the bottom of the screen. ŤŤ;;; In order to take out sections of code, place the mouse cursorŤ;;; at the left edge of the first line you want to take out. WithŤ;;; the left button held down, move the mouse cursor to the lastŤ;;; line you want to take out. The section of code should now beŤ;;; underlined. Without moving the mouse cursor, release the leftŤ;;; button. The code should stay underlined. ŤŤ;;; Type Control-W to delete the code from the original function.Ť;;; The code is now on the kill ring. Move the mouse cursor toŤ;;; the new position for the code. Click the left button once. Ť;;; Type Control-Y to put the code back into the buffer.ŤŤ;;; Then you have to check all of the parens to make them balanceŤ;;; in both the new function and the old. Do this for both DRAW-Ť;;; CIRCLES and DRAW-STRINGS. Remember to put in function callsŤ;;; where the code used to be. Note that the DRAW-STRINGS is notŤ;;; called correctly. This is deliberate, to provide practice atŤ;;; making and fixing another error. The code now looks like:ŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 9ŤŤŤ(DEFUN DRAW-CIRCLES (W MAX-X-SIZE MAX-Y-SIZE)Ť ‰(SEND W ':DRAW-CIRCLEŤ‰ (RANDOM MAX-X-SIZE)Ť‰ (RANDOM MAX-Y-SIZE)Ť‰ (RANDOM 100)))ŤŤŤ(DEFUN DRAW-STRINGS (W OUT-STRING MAX-X-SIZE MAX-Y-SIZE)Ť‰(SEND W ':SET-CURSORPOSŤ‰ (RANDOM MAX-X-SIZE)Ť‰ (RANDOMŤ‰‰(- MAX-Y-SIZE (* (SEND W ':LINE-HEIGHT) 2))))Ť‰(SEND W ':STRING-OUT OUT-STRING))ŤŤŤ(DEFUN DRFŤ (W &OPTIONAL (DRAW-CIRCLES T) (DRAW-STRINGS T)Ť‰(OUT-STRING "LINDA"))Ť (SEND W ':CLEAR-SCREEN)Ť (SEND W ':SET-FONT-MAP '(FONTS:BIGFNT FONTS:CPTFONT))Ť (SEND W ':SET-CURRENT-FONT 'FONTS:BIGFNT)Ť (LET ((MAX-X-SIZE (SEND W ':INSIDE-WIDTH))Ť‰(MAX-Y-SIZE (SEND W ':INSIDE-HEIGHT)))Ť (DO () ((SEND W ':TYI-NO-HANG) 'DONE)Ť (WHEN (< (RANDOM 100) 1)Ť‰(SEND W ':CLEAR-SCREEN))Ť (WHEN DRAW-CIRCLESŤ‰(DRAW-CIRCLES W MAX-X-SIZE MAX-Y-SIZE))Ť (WHEN DRAW-STRINGSŤ‰(DRAW-STRINGS W MAX-X-SIZE MAX-Y-SIZE)))))ŤŤŤŤ;;; Compile each of the new functions by putting the cursor inside,Ť;;; then typing Control-Shift-C. While compiling DRF, we get theŤ;;; message that OUT-STRING is bound but never used. Here we canŤ;;; look at the function, and remember where we used OUT-STRING.Ť;;; The logical place to examine is the code we removed and put inŤ;;; new functions. The function DRAW-STRINGS has more argumentsŤ;;; than we have supplied, so we fix that function call. We might Ť;;; also go to the LISP Listener and call DRF, then get the errorŤ;;; that we supplied only three arguments where we needed four andŤ;;; go back to the code in the editor buffer to fix it. After weŤ;;; fix the code by adding the required parameter, in the correctŤ;;; position, to the call to DRAW-STRINGS, drf looks like:ŤŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 10ŤŤŤ(DEFUN DRFŤ (W &OPTIONAL (DRAW-CIRCLES T) (DRAW-STRINGS T)Ť‰(OUT-STRING "LINDA"))Ť (SEND W ':CLEAR-SCREEN)Ť (SEND W ':SET-FONT-MAP '(FONTS:BIGFNT FONTS:CPTFONT))Ť (SEND W ':SET-CURRENT-FONT 'FONTS:BIGFNT)Ť (LET ((MAX-X-SIZE (SEND W ':INSIDE-WIDTH))Ť‰(MAX-Y-SIZE (SEND W ':INSIDE-HEIGHT)))Ť (DO () ((SEND W ':TYI-NO-HANG) 'DONE)Ť (WHEN (< (RANDOM 100) 1)Ť‰(SEND W ':CLEAR-SCREEN))Ť (WHEN DRAW-CIRCLESŤ‰(DRAW-CIRCLES W MAX-X-SIZE MAX-Y-SIZE))Ť (WHEN DRAW-STRINGSŤ‰(DRAW-STRINGS W OUT-STRING MAX-X-SIZE MAX-Y-SIZE)))))ŤŤŤŤŤ;;; This time it compiles all right, and tests all right.ŤŤŤ;;; Now change the function to draw just circles, but to draw them Ť;;; smaller and smaller, until they reach some minimum size. YouŤ;;; can make a new function from the existing functions by copyingŤ;;; and combining them, and modifying their behavior.ŤŤŤŤ(DEFUN DRAW-RECURSIVE-CIRCLESŤ (W MAX-X-SIZE MAX-Y-SIZE FIGURE-SIZE)Ť (COND ((< FIGURE-SIZE 1) 'DONE)Ť‰(TŤ‰ (SEND W ':DRAW-CIRCLEŤ‰ (RANDOM MAX-X-SIZE)Ť‰ (RANDOM MAX-Y-SIZE)Ť‰ FIGURE-SIZE)Ť‰ (DRAW-RECURSIVE-CIRCLES W MAX-X-SIZE MAX-Y-SIZEŤ‰‰‰‰ (- FIGURE-SIZE 2)))))ŤŤ ŤŤ(DEFUN DRAW-RECURSIVELY (W FIGURE-SIZE)Ť (SEND W ':CLEAR-SCREEN)Ť (SEND W ':SET-FONT-MAP '(FONTS:BIGFNT FONTS:CPTFONT))Ť (SEND W ':SET-CURRENT-FONT 'FONTS:BIGFNT)Ť (LET ((MAX-X-SIZE (SEND W ':INSIDE-WIDTH))Ť‰(MAX-Y-SIZE (SEND W ':INSIDE-HEIGHT))Ť‰(BASE 10))Ť (DRAW-RECURSIVE-CIRCLESŤ W MAX-X-SIZE MAX-Y-SIZE FIGURE-SIZE)))ŤŤŤŚ;;; LISP Programming LABŤ;;; Rapid PrototypingŤ;;; Page 11ŤŤŤ;;; Unfortunately, this doesn't look much different than before,Ť;;; probably because the circles are randomly drawn on the screen.Ť;;; Try making them draw with the same center point, as follows:ŤŤŤ(DEFUN DRAW-RECURSIVE-CIRCLESŤ (W MAX-X-SIZE MAX-Y-SIZE FIGURE-SIZE)Ť ‰(COND ((< FIGURE-SIZE 1) 'DONE)Ť‰ (TŤ‰ (SEND W ':DRAW-CIRCLEŤ‰‰ (// MAX-X-SIZE 2)Ť‰‰ (// MAX-Y-SIZE 2)Ť‰‰ FIGURE-SIZE)Ť‰ (DRAW-RECURSIVE-CIRCLESŤ‰‰ W MAX-X-SIZE MAX-Y-SIZE (- FIGURE-SIZE 2)))))ŤŤŤ;;; This function illustrates recursion nicely. In order to seeŤ;;; the recursive action of the function, make a new window forŤ;;; drawing in. Do this by executing the following:ŤŤŤ(SETQ FOO (MAKE-INSTANCE 'TV:WINDOW ':EDGES-FROM ':MOUSE))ŤŤŤ;;; This makes a window, with edges defined via mouse clicks {lookŤ;;; for a left hand, and then a right hand corner mouse blinker}.Ť;;; Position the window so that it covers the editor buffer, butŤ;;; not the Lisp Listener. ExecuteŤŤŤ(SEND FOO ':EXPOSE)ŤŤ(TRACE DRAW-RECURSIVE-CIRCLES)ŤŤ(DRAW-RECURISVELY FOO 150)ŤŤŤ;;; Every time DRAW-RECURSIVE-CIRCLES is executed, the call withŤ;;; its arguments are shown in the Lisp Listener, and a circle isŤ;;; drawn on the window foo. If you get a message that the PDL hasŤ;;; overflown, don't worry about it. Just hit . When youŤ;;; get tired of watching all the recursion, just hit . YouŤ;;; can also try more sophisticated tracing by going to the systemŤ;;; menu, clicking left on "Trace", typing DRAW-RECURSIVE-CIRCLESŤ;;; followed by a , then trying actions like "Break Before"Ť;;; or "Break On". These options allow you to examine environmentsŤ;;; within each call to the function, then continue via .Ť ŤŤ;;; When you are done with the demo, typeŤŤ;;; -1 MŤŤ;;; to turn "MORE Processing" back on.ŤŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 3 :LENGTH-IN-BYTES 2933 :AUTHOR "wilde" :CREATION-DATE 2716346362 :QFASLP NIL :LENGTH 2933 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "SPACE-FLAVOR" :TYPE "LISP" :VERSION 4) ŤŤŤŤŤŤ;;; Flavor demos modified from "Lisp Machine Programming" by James M. TurnerŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤŤ;;; Define a flavor for the class of SPACE-OBJECTŤ(defflavor space-objectŤ‰ ((x-pos 0) (y-pos 0) (z-pos 0)Ť‰ (x-vel 0) (y-vel 0) (z-vel 0)Ť‰ (mass 0))Ť ()Ť :settable-instance-variablesŤ :gettable-instance-variablesŤ :inittable-instance-variables)Ť;;; These keywords will create a group of machine-definedŤ;;; methods for getting, setting, and initializing Ť;;; instance variables.ŤŤŤ;;; Define a flavor for the class of SPACE-SHIP, which is built onŤ;;; the flavor SPACE-OBJECTŤ(defflavor space-shipŤ‰ ((x-thrust 0) (y-thrust 0) (z-thrust 0) (fuel 0) ship-name)Ť‰ (space-object)Ť :settable-instance-variablesŤ‰ :gettable-instance-variablesŤ‰ :inittable-instance-variables)ŤŤŤ;;; Inside a method, each instance variable is bound toŤ;;; its symbol name. Therefore, a variable such asŤ;;; X-POS can be used in the :MOVE method for SPACE-OBJECT.Ť;;; It will have whatever value the particular instance hadŤ;;; when it was called. In addition, if the value is Ť;;; changed here, the instance value is changed also.ŤŤ(defmethod (space-object :move) (time-fraction)Ť (setq x-pos (+ x-pos (* x-vel time-fraction))Ť‰y-pos (+ y-pos (* y-vel time-fraction))Ť‰z-pos (+ z-pos (* z-vel time-fraction))))ŤŤ(defmethod (space-ship :before :move) (time-fraction)Ť (if (plusp fuel)Ť (setq x-vel (+ x-vel (* x-thrust time-fraction))Ť‰ y-vel (+ y-vel (* y-thrust time-fraction))Ť‰ z-vel (+ z-vel (* z-thrust time-fraction))Ť‰ fuel (- fuel (* mass (+ x-thrust y-thrust z-thrust))))))ŤŤ(defmethod (space-ship :after :move) (ignore)Ť (format t "~%The Space Ship ~A is now at universal space position ~D:~D:~DŤIts velocity is ~D:~D:~DŤIts thrust is ~D:~D:~DŤYou've got ~D units of fuel left~%"Ť‰ ship-name x-pos y-pos z-pos x-vel y-vel z-velŤ‰ x-thrust y-thrust z-thrust fuel))ŤŚŤŤŤŤŤ;;; :INIT is a special method, defined by VANILLA FLAVOR.Ť;;; It can be used with an :AFTER modifier to make methodsŤ;;; act on an instance immediately after it is created.Ť(defmethod (space-ship :after :init) (&rest ignore)Ť (if (not (variable-boundp ship-name))Ť (setq ship-name "Name Me")))ŤŤ;;; Defining a new PRINT-SELF method will overwrite the Ť;;; standard method provided in VANILLA FLAVOR for Ť;;; printing the name of SPACE-SHIPŤ(defmethod (space-ship :print-self) (&rest ignore)Ť (format t "#" ship-name))ŤŤŤ(defflavor transport-mixinŤ‰ ((passengers 0) base-mass)Ť‰ ()Ť (:required-flavors space-ship)Ť :settable-instance-variablesŤ :inittable-instance-variables)ŤŤ(defmethod (transport-mixin :after :init) (&rest ignore)Ť (setq base-mass mass))ŤŤŤ(defmethod (transport-mixin :before :move) (&rest ignore)Ť (setq mass (+ base-mass (* passengers 180.))))ŤŤ(defflavor space-linerŤ‰ ()Ť‰ (transport-mixin space-ship))ŤŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 3 :LENGTH-IN-BYTES 2882 :AUTHOR "wilde" :CREATION-DATE 2725308345 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "SPACE-FLAVORS" :TYPE "LISP" :VERSION 1) ŤŤŤŤŤŤ;;; Flavor demos modified from "Lisp Machine Programming" by James M. TurnerŤŤ;;; Define a flavor for the class of SPACE-OBJECTŤ(defflavor space-objectŤ‰ ((x-pos 0) (y-pos 0) (z-pos 0)Ť‰ (x-vel 0) (y-vel 0) (z-vel 0)Ť‰ (mass 0))Ť ()Ť :settable-instance-variablesŤ :gettable-instance-variablesŤ :inittable-instance-variables)Ť;;; These keywords will create a group of machine-definedŤ;;; methods for getting, setting, and initializing Ť;;; instance variables.ŤŤŤ;;; Define a flavor for the class of SPACE-SHIP, which is built onŤ;;; the flavor SPACE-OBJECTŤ(defflavor space-shipŤ‰ ((x-thrust 0) (y-thrust 0) (z-thrust 0) (fuel 0) ship-name)Ť‰ (space-object)Ť :settable-instance-variablesŤ‰ :gettable-instance-variablesŤ‰ :inittable-instance-variables)ŤŤŤ;;; Inside a method, each instance variable is bound toŤ;;; its symbol name. Therefore, a variable such asŤ;;; X-POS can be used in the :MOVE method for SPACE-OBJECT.Ť;;; It will have whatever value the particular instance hadŤ;;; when it was called. In addition, if the value is Ť;;; changed here, the instance value is changed also.ŤŤ(defmethod (space-object :move) (time-fraction)Ť (setq x-pos (+ x-pos (* x-vel time-fraction))Ť‰y-pos (+ y-pos (* y-vel time-fraction))Ť‰z-pos (+ z-pos (* z-vel time-fraction))))ŤŤ(defmethod (space-ship :before :move) (time-fraction)Ť (if (plusp fuel)Ť (setq x-vel (+ x-vel (* x-thrust time-fraction))Ť‰ y-vel (+ y-vel (* y-thrust time-fraction))Ť‰ z-vel (+ z-vel (* z-thrust time-fraction))Ť‰ fuel (- fuel (* mass (+ x-thrust y-thrust z-thrust))))))ŤŤ(defmethod (space-ship :after :move) (ignore)Ť (format t "~%The Space Ship ~A is now at universal space position ~D:~D:~DŤIts velocity is ~D:~D:~DŤIts thrust is ~D:~D:~DŤYou've got ~D units of fuel left~%"Ť‰ ship-name x-pos y-pos z-pos x-vel y-vel z-velŤ‰ x-thrust y-thrust z-thrust fuel))ŤŚŤŤŤŤŤ;;; :INIT is a special method, defined by VANILLA FLAVOR.Ť;;; It can be used with an :AFTER modifier to make methodsŤ;;; act on an instance immediately after it is created.Ť(defmethod (space-ship :after :init) (&rest ignore)Ť (if (not (variable-boundp ship-name))Ť (setq ship-name "Name Me")))ŤŤ;;; Defining a new PRINT-SELF method will overwrite the Ť;;; standard method provided in VANILLA FLAVOR for Ť;;; printing the name of SPACE-SHIPŤ(defmethod (space-ship :print-self) (&rest ignore)Ť (format t "#" ship-name))ŤŤŤ(defflavor transport-mixinŤ‰ ((passengers 0) base-mass)Ť‰ ()Ť (:required-flavors space-ship)Ť :settable-instance-variablesŤ :inittable-instance-variables)ŤŤ(defmethod (transport-mixin :after :init) (&rest ignore)Ť (setq base-mass mass))ŤŤŤ(defmethod (transport-mixin :before :move) (&rest ignore)Ť (setq mass (+ base-mass (* passengers 180.))))ŤŤ(defflavor space-linerŤ‰ ()Ť‰ (transport-mixin space-ship))ŤŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 1 :LENGTH-IN-BYTES 792 :AUTHOR "SAM" :CREATION-DATE 2716748991 :QFASLP NIL :LENGTH 792 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "STREAMS" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;STREAMSŤŤ(provide 'streams)ŤŤŤ(defmacro make-empty-stream () `nil)Ť(defmacro empty-stream-p (stream) `(null ,stream))Ť(defmacro cons-stream (next rest) `(cons ,next ,rest))Ť(defmacro next-in-stream (stream) `(car ,stream))Ť(defmacro rest-of-stream (stream) `(cdr ,stream))ŤŤ(defmacro stream-of (element) `(cons-stream ,element (make-empty-stream)))ŤŤ(defun merge-streams (stream1 stream2)Ť (if (empty-stream-p stream1)Ť stream2Ť (cons-stream (next-in-stream stream1)Ť‰‰ (merge-streams stream2 (rest-of-stream stream1)))))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 37 :LENGTH-IN-BYTES 37660 :AUTHOR "ngl" :CREATION-DATE 2659445493 :QFASLP NIL :LENGTH 37660 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TEACH-ZMACS" :TYPE "TEXT" :VERSION 1) -*- Mode:Fundamental; Fonts:(HL12 HL12B HL12BI CPTFONT) -*-ŤŤYou are looking at the ZMacs tutorial. Comments on this document should beŤsent to Mark Dulcey at LMI.ŤŤZMacs is the editor used on the Lisp Machine. It is based on ZWEI, an editingŤsubsystem. Certain other programs on the Lisp Machine, such as ZMail andŤConverse, also use ZWEI. When you are editing text in these programs, it willŤbe with the same commands documented here. They also have other commandsŤof their own. Lisp Listeners have a 2rubout handler* which implements someŤsimple editing commands which are like ZMacs commands; type 1Help* in a LispŤListener to find out exactly what is available there.ŤŤZMacs commands generally involve the 1Control* key or the 1Meta* key. Rather thanŤwrite out 1Meta* or 1Control* each time we want you to prefix a character, we'll useŤthe following abbreviations:ŤŤ‰1C-2char**‰means hold the 1Control* key while typing the character 2char*.Ť‰‰‰Thus, 1C-F* would be: hold the 1Control* key and type 1F*. Do not Ť‰‰‰hold down the1 Shift* key. (Having 1Caps Lock* down is OK.)Ť ‰1M-2char**‰means hold the 1Meta* key down while typing 2char*.Ť‰1C-M-2char**‰means hold both the 1Control* key and the 1Meta* key down whileŤ‰‰‰typing 2char*.Ť‰1C-Sh-2char**‰means hold both the 1Control* key and the 1Shift* key down whileŤ‰‰‰typing 2char*.ŤŤImportant note: if you must exit at some point, you can use the 1System* key toŤtake you elsewhere. 1System* 1E* will get you back here. If you leave this tutorialŤand return to it in another session, 1System E* followed by 1M-X* 1Teach ZMacs* willŤreload the tutorial. (This will load the same private copy that you used last time;Ťif you saved any changes to it, those changes will still be there.)ŤŤThe characters "1>>*" at the left margin indicate directions for you to try using aŤcommand.ŤŤThe first thing that you need to know is how to move around from place to placeŤin the file. 1C-V *moves you forward to the next screen of text. 1M-V* takes youŤback to the previous screen.ŤŤ1>>*‰Now type 1C-V* (1Next Screen*) to move to the next screen.Ť‰(go ahead, do it by depressing the 1Control* key and 1V* together). Then typeŤ‰1M-V *to get back here.ŤŤFrom now on, you'll be expected to do this whenever you finish reading theŤscreen.ŤŤNote that there is an overlap when going from screen to screen; this providesŤsome continuity when moving through the file.ŤŤŤ2SUMMARY*ŤŤThe following commands are useful for viewing screenfuls:ŤŤ‰1C-V*‰Move forward one screenfulŤ‰1M-V*‰Move backward one screenfulŤ‰1C-L*‰Clear screen and redisplay everything putting the textŤ‰‰near the cursor at the center. ŤŤ1>>*‰Find the cursor and remember what text is near it.Ť‰Then type a 1C-L*.Ť‰Find the cursor again and see what text is near it now.ŤŤŤ2BASIC CURSOR CONTROL*ŤŤGetting from screenful to screenful is useful, but how do you reposition yourselfŤwithin a given screen to a specific place? There are several ways you can doŤthis. One way (not the best, but the most basic) is to use the commandsŤprevious, backward, forward and next. As you can imagine these commandsŤ(which are given to ZMacs as 1C-P*, 1C-B*, 1C-F*, and 1C-N* respectively) move theŤcursor from where it currently is to a new place in the given direction. Here, in aŤmore graphical form are the commands:Ť Ť‰‰‰ Previous line, 1C-P*Ť‰‰‰‰ :Ť‰‰‰‰ :Ť Backward, 1C-B* .... Current cursor position .... Forward, 1C-F*Ť‰‰‰‰ :Ť‰‰‰‰ :Ť‰‰‰ Next line, 1C-N*ŤŤYou'll probably find it easy to think of these by letter. 1P* for previous, 1N* forŤnext, 1B* for backward and 1F* for forward. These are the basic cursor positioningŤcommands and you'll be using them ALL the time so it would be of great benefit ifŤyou learn them now.ŤŤ1>>*‰Do a few 1C-N*'s to bring the cursor down to this line.ŤŤ1>>*‰Move into the line with 1C-F*'s and then up with 1C-P*'s.Ť‰See what 1C-P* does when the cursor is in the middle of the line.ŤŤLines are separated by a 1Return* character.ŤŤ1>>*‰Try to 1C-B* at the beginning of a line. Do a few more 1C-B*'s.Ť‰Then do 1C-F*'s back to the end of the line and beyond.ŤŤWhen you go off the top or bottom of the screen, the text beyond the edge isŤshifted onto the screen so that your instructions can be carried out while keepingŤthe cursor on the screen.ŤŤ1>>*‰Try to move the cursor off the bottom of the screen with 1C-N* andŤ‰see what happens.ŤŤIf moving by characters is too slow, you can move by words. 1M-F* movesŤforward a word and 1M-B* moves back a word.ŤŤ4>>*‰Type a few 1M-F*'s and 1M-B*'s. Intersperse them with 1C-F*'s and 1C-B*'s.ŤŤNotice the parallel between 1C-F* and 1C-B* on the one hand, and 1M-F* and 1M-B* onŤthe other hand. Very often 1Meta* characters are used for operations related toŤEnglish text whereas 1Control* characters operate on the basic textual units thatŤare independent of what you are editing (characters, lines, etc). There is a similarŤparallel between lines and sentences: 1C-A* and 1C-E* move to the beginning or endŤof a line, and 1M-A* and 1M-E* move to the beginning or end of a sentence.ŤŤ1>>*‰Try a couple of 1C-A*'s, and then a couple of 1C-E*'s.Ť‰Try a couple of 1M-A*'s, and then a couple of 1M-E*'s.ŤŤSee how repeated 1C-A*'s do nothing, but repeated 1M-A*'s keep moving farther. DoŤyou think that this is right?ŤŤTwo other simple cursor motion commands are 1M-<*, which moves to theŤbeginning of the file, and 1M->*, which moves to the end of the file. You probablyŤdon't need to try them, since finding this spot again will be boring.ŤŤThe location of the cursor in the text is also called "point". To paraphrase, theŤcursor shows on the screen where point is located in the text.ŤŤHere is a summary of simple moving operations including the word and sentenceŤmoving commands:ŤŤ‰1C-F*‰Move forward a characterŤ‰1C-B*‰Move backward a characterŤŤ‰1M-F*‰Move forward a wordŤ‰1M-B*‰Move backward a wordŤŤ‰1C-N*‰Move to next lineŤ‰1C-P*‰Move to previous lineŤŤ‰1C-A*‰Move to beginning of lineŤ‰1C-E*‰Move to end of lineŤŤ‰1M-A*‰Move back to beginning of sentenceŤ‰1M-E*‰Move forward to end of sentenceŤŤ‰1M-<*‰Go to beginning of fileŤ‰1M->*‰Go to end of fileŤŤ1>>*‰Try all of these commands now a few times for practice.Ť‰Since the last two will take you away from this screen,Ť‰you can come back here with 1M-V*'s and 1C-V*'s. These areŤ‰the most often used commands.ŤŤLike all other commands in ZMacs, these commands can be given arguments whichŤcause them to be executed repeatedly. The way you give a command a repeatŤcount is by holding down the 1Control* key, the 1Meta* key, or both, while typingŤdigits; then type the command.ŤŤFor instance, 1C-8* 1C-F* moves forward eight characters.Ť‰Ť1>>*‰Try giving a suitable argument to 1C-N* or 1C-P* to come as close‰Ť‰as you can to this line in one jump.ŤŤTwo exceptions to this is the screen moving commands, 1C-V* and 1M-V*. WhenŤgiven an argument, they scroll the screen up or down by that many lines, ratherŤthan screenfuls.ŤŤ1>>*‰Try typing 1C-8* 1C-V* now.ŤŤDid it scroll the screen up by 8 lines? If you would like to scroll it down you canŤgive an argument to 1M-V*.ŤŤAnother exception is the redisplay comand 1C-L*. When given an argument, itŤcauses the line where the cursor is located to be displayed that many lines fromŤthe top of the screen.ŤŤ1>>*‰Move the cursor to this line, then try try typing 1C-0 C-L*. This lineŤ‰should move to the top of the screen.ŤŤ2WHEN ZMacs IS HUNG*ŤŤIf ZMacs gets into an infinite (or simply very long) computation which you don'tŤwant to finish, you can stop it safely by typing 1C-Abort*. You can also useŤ1C-Abort* to discard a numeric argument or the beginning of a command that youŤdon't want to finish. (If the long computation was a Fill command or some similarŤcommand which moves text around in the buffer, the buffer may be left partiallyŤmodified.)Ť3 Ť1>>**‰Type 1C-100* to make a numeric arg of 100, then type 1C-Abort*.Ť‰Now type 1C-F*. How many characters does it move?ŤŤŤ2INSERTING AND DELETING*ŤŤIf you want to type text, just do it. Characters which you can see, such as 1A*, 17*,Ť1**, etc. are taken by ZMacs as text and inserted immediately. Type 1Return* toŤinsert a line separator.ŤŤYou can delete the last character you typed by typing 1Rubout*. 1Rubout* is a keyŤon the keyboard.1 *More generally, 1Rubout* deletes the character immediately beforeŤthe current cursor position. (The Delete key doesn't delete anything. In fact, itŤdoesn't do anything at all!)ŤŤ1>>*‰Do this now, type a few characters and then delete themŤ‰by typing 1Rubout* a few times. Don't worry about this fileŤ‰being changed; you won't affect the master tutorial. This is justŤ‰a copy of it.ŤŤ1>>*‰Now start typing text until you reach the right margin, and keepŤ‰typing. When a line of text gets too big for one line on theŤ‰screen, the line of text is "continued" onto a second screen line.Ť‰The exclamation mark at the right margin indicates a line which hasŤ‰been continued.ŤŤ1>>*‰Use 1Rubout*s to delete the text until the line fits on one screenŤ‰line again. The continuation line goes away.ŤŤ1>>*‰Move the cursor to the beginning of a line and type 1Rubout*. ThisŤ‰deletes the line separator before the line and merges the line ontoŤ‰the previous line. The resulting line may be too long to fit, inŤ‰which case it has a continuation line.ŤŤ1>>*‰Type 1Return* to insert the separator again.ŤŤRemember that most ZMacs commands can be given a repeat count; Note thatŤthis includes characters which insert themselves.ŤŤ1>>*‰Try that now -- type 1C-8* 1** and see what happens.ŤŤYou've now learned the most basic way of typing something in ZMacs andŤcorrecting errors. You can delete by words or lines as well. Here is a summaryŤof the delete operations:ŤŤ‰1Rubout*‰‰delete the character just before the cursorŤ‰1C-D*‰‰delete the next character after the cursorŤŤ‰1M-Rubout*‰kill the word immediately before the cursorŤ‰1M-D*‰‰kill the next word after the cursorŤŤ‰1C-K*‰‰kill from the cursor position to end of lineŤ‰1M-K*‰‰kill to the end of the current sentenceŤŤNotice that 1Rubout* and 1C-D* vs 1M-Rubout* and 1M-D* extend the parallel started byŤ1C-F* and 1M-F* (well, 1Rubout* isn't 2really* a control character, but let's not worryŤabout that). 1C-K* and 1M-K* are like 1C-E* and 1M-E*, sort of, in that lines areŤopposite sentences.ŤŤNow suppose you kill something, and then you decide that you want to get itŤback? Well, whenever you kill something bigger than a character, ZMacs saves itŤfor you. To yank it back, use 1C-Y*. Note that you don't have to be in the sameŤplace to do 1C-Y*; This is a good way to move text around. Also note that theŤdifference between 2Killing* and 2Deleting* something is that 2Killed* things can beŤyanked back, and 2Deleted* things cannot. (However, 2anything* can be undone;Ťsee the section 2Undoing changes*) Generally, the commands that can destroy aŤlot of text save it, while the ones that attack only one character, or nothing butŤblank lines and spaces, do not save.ŤŤFor instance, type 1C-N* a couple times to postion the cursor at some line on thisŤscreen.ŤŤ1>>*‰Do this now, move the cursor and kill that line with 1C-K*.ŤŤNote that a single 1C-K* kills the contents of the line, and a second 1C-K* kills theŤline itself, and make all the other lines move up. If you give 1C-K* a repeat count,Ťit kills that many lines AND their contents.ŤŤThe text that has just disappeared is saved so that you can retrieve it. ToŤretrieve the last killed text and put it where the cursor currently is, type 1C-Y*.ŤŤ1>>*‰Try it; type 1C-Y* to yank the text back.ŤŤThink of 1C-Y* as if you were yanking something back that someone took awayŤfrom you. Notice that if you do several 1C-K*'s in a row the text that is killed isŤall saved together so that one C1-Y *will yank all of the lines.ŤŤ1>>*‰Do this now, type 1C-K* several times.ŤŤNow to retrieve that killed text:ŤŤ1>>*‰Type 1C-Y*. Then move the cursor down a few lines and type 1C-Y*Ť‰again. You now see how to copy some text.ŤŤWhat do you do if you have some text you want to yank back, and then you killŤsomething else? 1C-Y* would yank the more recent kill. But the previous text isŤnot lost. You can get back to it using the 1M-Y* command. After you have doneŤ1C-Y* to get the most recent kill, typing 1M-Y* replaces that yanked text with theŤprevious kill. Typing 1M-Y* again and again brings in earlier and earlier kills. WhenŤyou have reached the text you are looking for, you can just go away and leave itŤthere. If you are using System 98 or greater, all kills made diring an entireŤsession are permanently recorded; in earlier system versions, only the mostŤrecent 8 kills are retained.Ť‰Ť1>>*‰Kill a line, move around, kill another line. Then do 1C-Y* to get backŤ‰the second killed line. Then do 1M-Y* and it will be replaced by theŤ‰first killed line. Do more 1M-Y*'s and see what you get. Keep doingŤ‰them until the second kill line comes back, and then a few more. IfŤ‰you like, you can try giving 1M-Y* positive and negative arguments.ŤŤŤ2THE MOUSE*ŤŤThe 2Mouse *(the little white or beige box with three buttons on top which isŤconnected to your keyboard or monitor by a cable) can be used to performŤvarious functions in ZMacs.ŤŤThe 2Mouse Cursor* tells you where the mouse is currently pointing. It is anŤarrow which points North-North-East while ZMacs is running. If you move theŤmouse, the pointer moves around the screen. Also, if you point the mouse at aŤcharacter (rather than at empty screen), the character is 2highlighted* byŤsurrounding it with a box.ŤŤ1>>*‰Roll the mouse around. Watch the mouse cursor move around the screen,Ť‰and how characters are highlighted when you point at them.ŤŤYou can move the position of the cursor by clicking the left mouse button once.ŤThe cursor moves to wherever the mouse cursor is. Clicking the left buttonŤtwice rapidly performs the inverse operation; the mouse cursor moves to meetŤthe cursor.ŤŤ1>>*‰Try moving around the cursor and the mouse cursor with mouse clicks.ŤŤThe mouse can also be used to 2scroll* the text in your buffer (the same thingŤthat comands like 1C-V* do). If you move the mouse to the upper right corner ofŤthe screen, you will notice that the mouse cursor changes to a fat arrow. RollingŤthe mouse toward the top of the screen here will let you see more text at theŤtop of the screen. Similarly, moving the mouse to the lower right corner will letŤyou see more text at the bottom.ŤŤ1>>*‰Move the text around a bit with the mouse now.ŤŤMoving the mouse to the left side of the screen allows various other sorts ofŤscrolling. The mouse cursor will change to a fat double-ended arrow to indicateŤthis. Clicking the left button will move the line pointed at to the top of theŤscreen. Clicking the right button will move the line which is at the top of theŤscreen to the location where the mouse cursor is. Note that a left click willŤundo the effect of a right click, and vice versa, if you do not move the mouseŤ(and you did not reach the beginning or the end of the buffer).ŤŤ1>>*‰Move up and down the screen with left-side clicks.ŤŤŤ2UNDOING CHANGES*ŤŤSometimes you may make a change to a file that you decide you really don't likeŤafter all. Or perhaps you accidentally typed an unfamiliar command, and youŤdon't know what it was! All is not lost; you can easily 2undo* your change to yourŤtext. The command 1C-Sh-U* (1Quick Undo*) will remove the most recent change youŤmade to the buffer, restoring it to its previous state. The cursor is also movedŤto the position of the undone change, so you can see what it was. (Any numberŤof characters inserted and/or deleted without moving the cursor are considered aŤsingle change. Certain other simple changes are also combined.) All the changesŤyou made since the last time you saved the file are remembered; typing moreŤ1C-Sh-U* commands will undo changes in reverse order until no more are left.ŤŤIf you undo a change, and decide you really liked the changed version better, allŤis 2still* not lost! You can 2redo* any changes you previously undid with theŤcommand 1C-Sh-R* (1Quick Redo*); this puts your change back into the buffer. IfŤyou don't like it after all, you can always undo it again.ŤŤThere are also extended commands available for undoing and redoing. The 1M-XŤUndo* command will tell what it is about to undo, and ask whether you want toŤundo it or not. Similarly, the 1M-X Redo* command will tell you what it is about toŤredo. (I find it easier to just go ahead and undo the change quickly and look atŤthe new state; it's easy to redo it if you don't like that.)ŤŤ1>>*‰Make some changes to this buffer. Undo and redo them.ŤŤŤ2FILES*ŤŤIn order to make the text you edit permanent, you must put it in a file.ŤOtherwise, it will go away when your invocation of ZMacs goes away. You putŤyour editing in a file by 2finding* the file. What finding means is that you see theŤcontents of the file in your ZMacs; and, loosely speaking, what you are editing isŤthe file itself. However, the changes still don't become permanent until you 2save*Ťthe file. This is so you can have control to avoid leaving a half-changed fileŤaround when you don't want to. If you are using a host which supports versionŤnumbers for files (such as the Lisp Machine File System, the LMFILE system, ITS,ŤTOPS-20, or VAX-VMS), saving will create a new version of your file; theŤoriginal will still be intact until you delete it. ŤŤIf you look near the botton of the screen you will see a line that starts withŤ"ZMACS (Fundamental) TEACH-ZMACS.TEXT ; LAM1:" (if youŤare logged in to LAM1. (The form of the name may be different if you are loggedŤin to a different host.) This is the name of your own copy of the text of theŤZMacs tutorial; the file you are now looking at. Whatever file you find, that file'sŤname will appear in that precise spot.ŤŤThe commands for finding and saving files are unlike the other commands youŤhave learned in that they consist of two characters. They both start with theŤcharacter 1Control-X*. There is a whole series of commands that start withŤ1Control-X*; many of them have to do with files, buffers, and related things, and allŤof them consist of 1Control-X* followed by some other character. (Control-XŤcommands will be written in the form 1C-X Q* in the rest of this document.)ŤŤAnother thing about the command for finding a file is that you have to say whatŤfile name you want. We say the command "reads an argument from the terminal"Ť(in this case, the argument is the name of the file). After you type theŤcommandŤŤ‰1C-X* 1C-F*‰Find FileŤŤZMacs will ask you for the file name. You should end the name with the ReturnŤkey. This command will read the file into its own new buffer. (If you use Find FileŤon a file which is already in your ZMacs, you will simply be switched to thatŤbuffer; the file is not read in again.) After this command, you will see theŤcontents of the file in your ZMacs. You can edit the contents. When you wishŤto make the changes permanent, issue the commandŤŤ‰1C-X C-S*‰Save FileŤŤThe file will be saved. If the host file system supports version numbers, a newŤversion of the file will be created. When the operation is finished, ZMacsŤprints the name and version saved. You should save fairly often, so that you willŤnot lose very much work if your Lisp Machine should crash. (If the hostŤcomputer crashes, you can simply wait for it to work again, then retry the save.)ŤŤ‰1C-X C-W*‰Write FileŤŤThis causes the buffer to be written out to a file, like Save File does. TheŤdifference is that you will be asked for a name to write it under. This lets youŤput your new text in a different place from the original. (This is especiallyŤuseful if your host does not support version numbers!) The buffer will also beŤrenamed to the new file name, so any subsequent Save File commands will alsoŤoutput to the new file.Ť ŤTo make a new file, just find it "as if" it already existed. Then start typing inŤthe text. When you ask to save the file, ZMacs will really create the file withŤthe text that you have inserted. From then on, you can consider yourself to beŤediting an already existing file.ŤŤ1>>*‰Try finding a new file now. (The name will depend on which host you areŤ‰logged into.) Put some text into it, and save it. When you are done, you canŤ‰come back here with 1C-M-L*. (More generally, 1C-M-L* returns you to theŤ‰buffer you were editing most recently before the current one.)ŤŤŤ2EXTENDING THE COMMAND SET*ŤŤThere are many, many more ZMacs commands than could possibly be putŤon all the control and meta characters. ZMacs gets around this withŤthe 1X* (2eXtend*) command. This comes in two flavors:ŤŤ‰1C-X*‰Character 2eXtend*. Followed by one character.Ť‰1M-X*‰Named command 2eXtend*. Followed by a long name.ŤŤThese are commands that are generally useful but used less than the commandsŤyou have already learned about. You have already seen two of them: the fileŤcommands 1C-X* 1C-F* to Find and 1C-X* 1C-S* to Save. ŤŤThere are many 1C-X* commands. The ones you need immediately are:ŤŤ‰1C-X* 1C-F*‰‰Find file.Ť‰1C-X* 1C-S*‰‰Save file.Ť‰1C-X C-W*‰‰Write file.ŤŤNamed extended commands are commands which are used even lessŤfrequently, or commands which are used only in certain modes. TheseŤcommands are usually called 2functions*. An example is the functionŤ1Replace String*, which globally replaces one string with another. WhenŤyou type 1M-X*, ZMacs prompts you at the bottom of the screen withŤ1M-X* and you should type the name of the function you wish to call; inŤthis case, 1Replace String*. Just type "1REPL*" and ZMacs willŤcomplete the name. You will be prompted for the string to replace; type itŤfollowed by 1Return*. Then you will be prompted for the new string; type itŤfollowed by 1Return*.ŤŤ1>>*‰Move the cursor to the blank line two lines below this one.Ť‰Then type 1M-X* 1replchangedaltered*.ŤŤNotice how this line has changed: you've replaced the word 1changed* with 1altered*Ťwherever it occurs after the cursor.ŤŤŤ2MODE LINE*ŤŤIf ZMacs sees that you are typing commands slowly it shows them to you at theŤbottom of the screen in an area called the echo area. The echo area containsŤthe bottom three lines of the screen. The line immediately above them is calledŤthe 2mode line*. The mode line says something likeŤŤ‰ZMACS (Modename) Filename (ver) Font: A (fontname) 3  **ŤŤYou already know what the filename means -- it is the file you have found.1 *TheŤstar at the very end of the mode line means that you have made changes to theŤtext. Right after you find or save a file, there is no star.ŤŤThe font information is displayed only if the file you are editing contains moreŤthan one font. It tells what the current 2default font* is. See the section onŤ2Using multiple fonts* for more information on this.ŤŤThe arrows just before the star at the end of the mode line indicate whetherŤthere is more text in the buffer above and below the current screen. If theŤup-arrow appears, there is more text before the current screen. If theŤdown-arrow appears, there is more text after the current screen. If both appear,Ťthere is more both before and after; if neither appears, the present screen is allŤthere is.ŤŤ1>>*‰Move the the beginning and the end of this buffer; watch the "more text"Ť‰indicators change.ŤŤThe part of the mode line inside the first set ofparentheses is to tell you whatŤmodes you are in. (The default mode is Lisp, unless the type field in the fileŤname causes a different default to be used; for example, any filename with a typeŤof 2TEXT* will be edited in Text Mode by default if it has no attributes list.ŤHowever, a file may specify which mode it likes in an Attributes List. ThisŤappears as the first line of the file. This file specifies Fundamental mode.) It isŤan example of a 2major mode*. There are several major modes in ZMacs forŤediting different languages and text, such as LISP mode, Text mode, etc. At anyŤtime one and only one major mode is active, and its name can always be found inŤthe mode line just where "Fundamental" is now. Each major mode makes a fewŤcommands behave differently. For example, there are commands for creatingŤcomments in a program, and since each programming language has a different ideaŤof what a comment should look like, each major mode has to insert commentsŤdifferently. Each major mode is the name of an extended command, which is howŤyou get into the mode. For example, 1M-X Lisp* 1Mode* is how to get into LispŤmode.ŤŤIf you are going to edit English language text, you should use Text mode.ŤŤ1>>*‰Type 1M-X Text Mode* to get to Text mode. Notice how the mode line changes.ŤŤDon't worry, none of the commands you have learned changes ZMacs in anyŤgreat way. Major modes are usually like that: commands don't change intoŤcompletely unrelated things, but they work a little bit differently. Lisp Mode addsŤcommands appropriate to editing Lisp programs. Text Mode causes underscoreŤ(3_*) and quote (') characters to be considered part of words.ŤŤMajor modes are called major because there are also 2minor modes*. They areŤcalled minor because they aren't alternatives to the major modes, just minorŤmodifications of them. Each minor mode can be turned on or off by itself,Ťregardless of what major mode you are in, and regardless of the other minorŤmodes. So you can use no minor modes, or one minor mode, or anyŤcombination of several minor modes.ŤŤOne minor mode which is very useful, especially for editing English text, is AutoŤFill mode. When this mode is on, ZMacs breaks the line in between wordsŤautomatically whenever the line gets too long. You can turn this mode on byŤdoing 1M-X Auto Fill Mode*. When the mode is on, you can turn it off by doingŤ1M-X Auto Fill Mode*. If the mode is off, this function turns it on, and if the modeŤis on, this function turns it off. This is called 2toggling*.ŤŤ1>>*‰Type 1M-X Auto Fill Mode* now. Then insert a line of "asdf "Ť‰over again until you see it divide into two lines. You must put inŤ‰spaces between them because Auto Fill breaks lines only at spaces.Ť‰Notice that "Fill" appears in the mode line in addition to the nameŤ‰of the major mode, not instead of it.ŤŤThe margin is usually set at 576 pixels (dots on the screen), but you can changeŤit with the 1C-X* 1F* command. You move the cursor where you want the fill columnŤto be, then type 1C-X* 1F*. You can also give 1C-X* a numeric argument. If it lessŤthan 200., it specifies the fill column in characters. An argument >= 200. specifiesŤa fill column in pixels. ŤŤ1>>*‰Move the cursor to column 20 (or thereabouts) and type 1C-X F*. Then typeŤ‰some lines and watch ZMacs fill them.ŤŤ1>>*‰Set the fill column back to its original value by typing 1C-X F* with an argumentŤ‰of 1576*.ŤŤŤ2SEARCHING*ŤŤZMacs can do 2searches* for strings (these are groups of contiguous charactersŤor words) either forward through the file or backward through it. To search forŤthe string means that you are trying to locate it somewhere in the file and haveŤZMacs show you where the occurrences of the string exist. This type ofŤsearch is somewhat different from what you may be familiar with. It is a searchŤthat is performed as you type in the thing to search for. The command toŤinitiate a search is 1C-S* for forward search, and 1C-R* for reverse search. 2BUTŤWAIT!* Don't do them now. When you type 1C-S* you'll notice that the stringŤ"I-search" appears as a prompt in the echo area. This tells you that ZMacs is inŤwhat is called an 2incremental search* waiting for you to type the thing thatŤyou want to search for. 1Altmode* terminates a search.Ť‰Ť1>>*‰Now type 1C-S* to start a search. 2Slowly*, one letter at a time, type the wordŤ‰1cursor*, pausing after you type each character to notice what happens to theŤ‰cursor.ŤŤ1>>*‰Type 1C-S* to find the next occurrence of 1cursor*.ŤŤ1>>*‰Now type 1Rubout* four times and see how the cursor moves.ŤŤ1>>*‰Type 1Altmode* to terminate the search.ŤŤDid you see what happened? ZMacs, in an incremental search, tries to go toŤthe occurrence of the string that you've typed out so far. To go to the nextŤoccurrence of 'cursor' just type 1C-S* again. If no such occurrence exists ZMacsŤbeeps and tells you that it is a failing search.ŤŤIf you are in the middle of an incremental search and type 1Rubout*, you'll noticeŤthat the last character in the search string is erased and the search backs up toŤthe last place of the search. For instance, suppose you currently have typedŤ1cu* and you see that your cursor is at the first occurrence of 1cu*. If you nowŤtype 1Rubout*, the 1u* on the search line is erased and you'll be repositioned in theŤtext to the occurrence of 1c* where the search took you before you typed the 1u*.ŤThis provides a useful means for backing up while you are searching.ŤŤIf you are in the middle of a search and happen to type a control characterŤ(other than a 1C-S* or 1C-R*, which tell ZMacs to search for the next occurrenceŤof the string, or a 1C-Q*, which can be used to input certain 1Top* and 1Greek*Ťcharacters for compatibility with certain other systems), the search isŤterminated, and the character is executed. 1Abort* will simply end the search, likeŤ1Altmode*.ŤŤThe 1C-S* starts a search that looks for any occurrence of the search stringŤ2after* the current cursor position. But what if you want to search forŤsomething earlier in the text? To do this, type 1C-R* for Reverse search.ŤEverything that applies to 1C-S* applies to 1C-R* except that the direction of theŤsearch is reversed.ŤŤŤ2GETTING MORE HELP*ŤŤIn this tutorial we have tried to supply just enough information toŤget you started using ZMacs. There is so much available in ZMacs thatŤit would be impossible to explain it all here. However, you may wantŤto learn more about ZMacs since it has numerous desirable featuresŤthat you don't know about yet. ZMacs has a great deal of internalŤdocumentation. All of these commands can be accessed through the 1Help*Ťcharacter.ŤŤTo use the 2Help* features, type 1Help*, and then a character saying what kind ofŤhelp you want. If you are 2really* lost, type 1Help* 1Help* and ZMacs will tell youŤwhat kinds of help it can give. If you have typed the 1Help* character and decideŤyou don't want any help, just type 1Abort* to abort.ŤŤThe most basic Help feature is 1Help* C. Type 1Help*, a 1C*, and a commandŤcharacter, and ZMacs prints a description of the command. When you areŤfinished reading it, type a 1Space* or an= 1Abort** to bring your text back on theŤscreen.ŤŤ>>‰Type 1Help* 1C* 1Control-P*. When you are finished reading the output,Ť‰type a 1Space*. The message should be something likeŤ1 *Ť‰Control-P is Up Real Line, implemented by COM-UP-REAL-LINE:Ť‰Move up vertically to previous real line.Ť‰Moves as far as possible horizontally toward the goal column for successiveŤ‰commands.ŤŤThe "name of the function" is important for people who are customizing ZMacs.ŤIt is what appears in the ZMacs Chart as the documentation for the commandŤcharacter. For now you can ignore it.ŤŤMulti-character commands such as 1C-X* 1C-F* are also allowed after 1Help* 1C*.ŤŤHere are some other useful 1Help* options:ŤŤ 1Help* 1D*‰Describe a function. You type in the name of theŤ‰‰function. To see your text again when it is done,Ť‰‰type a 1Space* or 1Abort*.ŤŤ1>>*‰Try typing 1Help* 1D Replace String*. Then type a1 Space* when you areŤ‰finished reading it.ŤŤ 1Help* 1A*‰Apropos. Type in a keyword and ZMacs will listŤ‰‰all the functions containing that keyword. For someŤ‰‰functions it will also list a one or two characterŤ‰‰command which has the same effect.ŤŤ1>>*‰Type 1Help* 1A File*. You will see a list of all functions (1M-X* commands)Ť‰with "file" in their names. You will also see commands like 1C-X* 1C-F* and 1C-X*Ť‰1C-S*, listed under the corresponding function names. When it says "**MORE**"Ť‰at the bottom of the screen, type a 1Space* to see the rest of the list, orŤ‰1Abort* to abort the rest of the listing.ŤŤ 1Help L *This tells you what the last 60. characters you typed were. If youŤ‰ don't know what you did to make something happen, this can beŤ‰ useful.ŤŤŤ2USING MULTIPLE FONTS*ŤŤOne of the things which you surely noticed about this file is the use of multipleŤtypefaces, or 2fonts*, for various things in the file. Using multiple fonts can makeŤyour document much more readable. Also, if you are using the LMI printerŤsoftware with an appropriate printer, your files can be printed in multiple fonts.ŤŤThe first thing you must do when you create your file is use the 1M-X Set Fonts*Ťcommand. This lets you name the fonts you want to use in your file. You typeŤthe font names you want, separated by spaces. The order is significant; we willŤget to that in a moment. After you type the fonts, you will be asked "ChangeŤthe -*- line of the file as well?". You should answer 1Y* to this question. ThisŤcauses a 2File attribute list* to be created (or updated, if the file already hasŤone) at the top of the file. (This file has one, for example; it specifies the fourŤfonts which are used in this file, and specifies Fundamental Mode as the mode inŤwhich the file should be edited. If your file is being edited in Lisp Mode, theŤattribute list will be put inside a comment, so it will not affect your program.ŤŤ1>>*‰Move to the top of the file and look at the attribute list.ŤŤThis document uses four fonts: 2HL12* (Helvetica 12 point) is used for the mainŤtext of the file. 2HL12B* (Helvetica 12 point bold) is used for ZMacs commandsŤand character names. 2HL12BI* (Helvetica 12 point bold italic) is used for sectionŤheadings and for emphasis in the text; 2CPTFONT* (named after a brand ofŤmonitor used on early Lisp Machines) is used for characters (like the up and downŤarrows and underscores) which do not exist in some of the other fonts. ThereŤare many other fonts available; the command 1M-X List Fonts* will tell you whatŤthey all are, and clicking the mouse on one of the font names displayed by thatŤcommand will allow you to see what a font looks like. If you give the 1List Fonts*Ťcommand a numeric argument, it will list fonts on the system directory (SYS:ŤFONTS;) in addition to the fonts that are already loaded. Note that a few of theŤfonts contain special symbols like arrows; these are not intended for normal text.ŤThese special fonts are used for such things as the mouse cursor. (2MOUSE* andŤ2NARROW* are examples of special fonts.) 2CPTFONT* is the default font for mostŤwindows on the Lisp Machine, and the wholine is always displayed in that font.ŤŤIf you want to type a number of things in a new font, the 1C-M-J* (1Change* 1DefaultŤFont*) command is what you are looking for. This changes the 2default font*; thatŤis, the font which will be used for any new characters which are typed into theŤbuffer. You specify the new font by giving a letter; font A is the first font inŤthe attribute list, font B is the second one, and so on. When the file is first readŤin, font A will be the default font, so it should be the font most often used.ŤŤ1>>*‰Change the default font to 1B* (1HL12B*). Type some text.ŤŤThere are also various commands for changing the font of text which is alreadyŤin the buffer. 1C-J* (1Change Font Char*) changes the font of one character at aŤtime (or the number of characters specified by an argument). You will beŤaskedfor a font to use in the same way as in 1C-M-J. *If you give successiveŤ1C-J* commands without moving the cursor, you will not be asked for the new fontŤafter the first one; it is assumed that you want to continue changing charactersŤto the same font. (If that is not what you want, simply move the cursor aŤcharacter forward, move it back, then proceed with the 1C-J* command.ŤŤ1M-J* (1Change Font Word*) lets you change the font of existing text one word at aŤtime. It is otherwise similar to 1C-J*. 1C-X C-J* (1Change Font Region*) changes theŤfont of all the characters in the region.ŤŤŤ2CONCLUSION*ŤŤRemember, to exit, use the 1System* key. (1System* 1Help* will tell you what systemŤcommands are accepted.) Make sure to save any files you need saved beforeŤexiting.ŤŤUnfortunately, there is no ZMacs manual yet. You may, however, find anŤEMACS manual to be useful. Most of the commands documented there alsoŤwork in ZMacs.ŤŤThis tutorial is meant to be understandable to all new users, so ifŤyou found something unclear, don't sit and blame yourself - complain!ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 12 :LENGTH-IN-BYTES 12014 :AUTHOR "pace" :CREATION-DATE 2669619061 :QFASLP NIL :LENGTH 12014 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE" :TYPE "LISP" :VERSION 2) ;;; -*- Package: ICON; Mode: LISP; Base: 10 -*-Ť;Ť; YATI (Yet another Turtle Implementation)Ť; Copyright 1984, Steve StrassmannŤ;Ť; This software is in the public domain. You may freely distribute itŤ; for educational purposes and incorporate it in other publicŤ; domain software, but it can not be incorporated into a productŤ; and sold without permission from the author.Ť;Ť; To use this file: Ť; No other files need to be loaded. Ť; This provides the basic building blocks for other, neater turtles.Ť;Ť; Experienced logoites will need no introduction; others can justŤ; try loading DEMO-ICON and playing with the turtles.Ť; Ť;------------------------------------------------------------------------------Ť;Ť; This file defines the following flavors:Ť;Ť; BASIC-TURTLE, which acts like a standard LOGO turtleŤ; POND-MIXIN, a window mixin which handles turtles.Ť; Always mix in this flavor to any window which willŤ; have turtles on it.ŤŤ;==============================================================================Ť;Ť; Basic Turtles are things which obey standard LOGO-type turtle commands.Ť; They look like triangles pointed in a certain direction (specified in degrees,Ť; with 0 degrees meaning pointing toward the top of the screen), at a certainŤ; position in the screen.Ť;Ť; You can send them these messages:Ť;Ť; :FORWARD :FD Ť; :BACKWARD :BK Ť; :LEFT :LT Ť; :RIGHT :RT Ť; :PENUP :PUŤ; :PENDOWN [] :PD [] is optional. It defaults to :DOWN (ior).Ť; Others are :IOR, :XOR, :ERASE; :UP, T & NILŤ; :HIDE Makes the turtle invisible.Ť; :UNHIDE Makes the turtle visible.Ť; :HOME Puts turtle in the screen's center, facing up.Ť; :CS Clears the turtle's screen.Ť; :SET-POS Ť; :SET-HEADING Ť; :SET-WINDOW Move the turtle to a new window.Ť;Ť; You can make a turtle with Ť;Ť; (MAKE-TURTLE . )Ť; Window must have POND-MIXIN.Ť; After the window come alternating keywords and valuesŤ; for initializing the turtle. Its position defaults toŤ; the HOME position: center of the pond, facing up.Ť; Ť;==============================================================================Ť;Ť; This is a window which has turtles on itŤ;Ť;Ť; It keeps track of its turtles with the following messages:Ť;Ť; :ADD-TURTLE Ť; :REMOVE-TURTLE Ť; :TELL-TURTLES [ ... ]Ť;Ť;Ť(defflavor pond-mixinŤ‰((turtles nil))Ť‰(tv:graphics-mixin tv:stream-mixin)‰; This stream has nothing to do with ponds.Ť :initable-instance-variables‰‰‰; It's the boring old lispm STREAM mixin.Ť :gettable-instance-variablesŤ :settable-instance-variables)ŤŤ(defmethod (pond-mixin :after :refresh) (&rest ignore)Ť (loop for turtle in turtlesŤ‰do (send turtle ':set-drawn? nil)‰; Inform the turtle it's been erased.Ť‰do (send turtle ':draw)))‰‰; Draw it and make it visible.ŤŤ(defmethod (pond-mixin :add-turtle) (turtle)Ť (setq turtles (cons turtle turtles)))ŤŤ(defmethod (pond-mixin :remove-turtle) (turtle)Ť (setq turtles (remq turtle turtles)))ŤŤ; &REST takes the rest of the arguments and makes a list, ARGS.Ť; Lexpr-funcall unravels its last argument and passes its contentsŤ; to the function being called.Ť; Thus, for example, (lexpr-funcall '+ 1 1 '(1 1)) returns 4.Ť;Ť; You could send a message like (send window ':tell-turtles ':forward 100)Ť; and all the turtles would go forward 100.Ť;Ť(defmethod (pond-mixin :tell-turtles) (message &rest args)Ť (loop for turtle in turtlesŤ‰do (lexpr-funcall turtle message args)))ŤŤŤ;==============================================================================ŤŤŤ(defflavor basic-turtleŤ‰((xcor nil)Ť‰ (ycor nil)Ť‰ (pen ':down)Ť‰ (hidden? nil)‰‰‰‰; Hidden turtles don't want to get drawn.Ť‰ (drawn? nil)‰‰‰‰; Undrawn, non-hidden turtles get drawn.Ť‰ (heading 0)‰‰‰‰; 0 degrees is due North.Ť‰ (height 5)‰‰‰‰; 1/3 height of the turtle's triangle Ť‰ (width 5)‰‰‰‰; 1/2 base of the turtle's triangleŤ‰ (window nil))Ť‰()Ť :initable-instance-variablesŤ :gettable-instance-variablesŤ :settable-instance-variables)ŤŤ; You can make a turtle with (MAKE-TURTLE . )Ť; For example, (SETQ FRED (MAKE-TURTLE *MY-WINDOW ':XCOR 50 ':HEADING 180))Ť;Ť; The window must have POND-MIXIN. After the window come alternatingŤ; keywords and values for initializing the turtle. The turtle's position defaultsŤ; to the HOME position: center of the pond, facing up. (see the :INIT method)Ť;Ť(defmacro make-turtle (window . options)Ť `(make-instance 'basic-turtle ':window ,window . ,options))ŤŤ; SET-POS and SET-HEADING handle going beyond limits so nothing else has to.Ť; The position is in screen coordinates.Ť;Ť(defmethod (basic-turtle :set-pos) (x y)Ť (if (not hidden?) (send self ':erase))Ť (setq xcor (wrap x (send window ':width))Ť‰ycor (wrap y (send window ':height)))Ť (if (not hidden?) (send self ':draw)))ŤŤ; Degrees, not radians. 0 degrees is straight up.Ť;Ť(defmethod (basic-turtle :set-heading) (h)Ť (send self ':erase)Ť (setq heading (wrap h 360))Ť (send self ':draw))ŤŤ; Confines x to the interval 0  x  bound.Ť; Probably faster than modulo, though I never benchmarked it.Ť;Ť(defun wrap (x bound)‰‰‰ Ť (cond ((minusp x) (wrap (+ x bound) bound))Ť‰((> x bound)(wrap (- x bound) bound))Ť‰(t x)))ŤŤ; The three corners of the triangle are rotated relative to the center.Ť; If the turtle were facing north, its corners would have the followingŤ; relative coordinates:Ť; Top x: 0 y: (* 2 height) *Ť; Left x: -width y: -height ***Ť; Right x: width y: -height *****ŤŤ(defmethod (basic-turtle :draw) ()Ť (if (or hidden? drawn?) nil‰ ‰; don't draw hidden or already drawn turtles.Ť (send window ':draw-triangle‰‰‰; draw-triangle takes 7 arguments:Ť‰ (fixr (+ xcor (rotx 0 (* 2 height) heading)))‰; x1Ť‰ (fixr (- ycor (roty 0 (* 2 height) heading)))‰; y1Ť‰ (fixr (+ xcor (rotx (- width) (- height) heading)))‰; x2Ť‰ (fixr (- ycor (roty (- width) (- height) heading)))‰; y2Ť‰ (fixr (+ xcor (rotx width (- height) heading)))‰; x3Ť‰ (fixr (- ycor (roty width (- height) heading)))‰; y3Ť‰ tv:alu-xor) ‰‰‰ ; aluŤ (setq drawn? t)))ŤŤ(defmethod (basic-turtle :erase) ()Ť (if (not drawn?) nil‰‰ ‰; don't erase undrawn turtlesŤ (send window ':draw-triangle‰‰‰; draw-triangle takes 7 arguments:Ť‰ (fixr (+ xcor (rotx 0 (* 2 height) heading)))‰; x1Ť‰ (fixr (- ycor (roty 0 (* 2 height) heading)))‰; y1Ť‰ (fixr (+ xcor (rotx (- width) (- height) heading)))‰; x2Ť‰ (fixr (- ycor (roty (- width) (- height) heading)))‰; y2Ť‰ (fixr (+ xcor (rotx width (- height) heading)))‰; x3Ť‰ (fixr (- ycor (roty width (- height) heading)))‰; y3Ť‰ tv:alu-xor) ‰‰‰ ; aluŤ (setq drawn? nil)))ŤŤŤ; This returns the X-coordinate of the rotated pointŤ;Ť(defun rotx (x y theta)Ť (+ (* x (cosd theta))Ť (* y (sind theta))))ŤŤ; This returns the Y-coordinate of the rotated pointŤ;Ť(defun roty (x y theta)Ť (- (* y (cosd theta))Ť (* x (sind theta))))ŤŤ;------------------------------------------------------------------------------ŤŤ; Let's keep track of every turtle ever created automatically.Ť; The window should have the flavor POND-MIXIN mixed in.Ť;Ť(defmethod (basic-turtle :after :init) (&rest ignore)Ť (if (null window)Ť nil‰‰‰‰‰; Can't do anythingŤ (send window ':add-turtle self)Ť (or xcor (setq xcor (* .5 (send window ':width))))Ť (or ycor (setq ycor (* .5 (send window ':height))))Ť (send self ':draw)))ŤŤ(defmethod (basic-turtle :before :set-window) (ignore)Ť (and window (send window ':remove-turtle self)))ŤŤ(defmethod (basic-turtle :after :set-window) (new-window)Ť (and new-window (send new-window ':add-turtle self)))ŤŤ;------------------------------------------------------------------------------Ť; Go forward (move ahead, whip it, whip it good ......)Ť;Ť(defmethod (basic-turtle :forward) (n)Ť (let* ((dx (* (sind heading) n))Ť‰ (dy (* (cosd heading) -1 n))‰‰; Remember that Y increases downwardsŤ‰ (nx (+ xcor dx))‰‰‰; on the lisp machine....Ť‰ (ny (+ ycor dy)))Ť (send self ':handle-pen dx dy nx ny)Ť (send self ':set-pos nx ny)))ŤŤ; Wraparound is the notion that going off to one side makes you show up on theŤ; other side. Our turtles "wrap" when they try to leave the screen.Ť; :HANDLE-PEN must draw one line if the turtle's movement is totally on-screen,Ť; and two lines if there's wraparound. Clipping (trimming the length of the lines)Ť; isn't necessary, since the lisp machine will merely ignore the part of theŤ; line that lies off-screen. I use the following position variables:Ť;Ť; DX,DY: change in position. NX,NY: unclipped new position. WX,WY: wrapped new position.Ť;Ť; PEN must be bound to a keyword or T or NIL. This tells the turtle what kind ofŤ; line to draw. PICK-ALU decides which kind of alu to use when drawing; for more infoŤ; on alu's, see the Window system manual. These keywords are defined:Ť; :IOR, :XOR, :ERASE, :UP (does nothing), :DOWN (inclusive or).Ť; Also, T means :DOWN and NIL means :UP.Ť;Ť; Note that the turtles are erased. This is kind of like lifting up your feetŤ; before painting the floor; an inaccurate line would be drawn if the turtleŤ; stayed on the screen.Ť;Ť(defmethod (basic-turtle :handle-pen) (dx dy nx ny)Ť (if (or (null pen) (eq pen ':up))Ť nil‰‰‰‰‰; don't draw a line if the pen is up.Ť (send window ':tell-turtles ':erase)Ť (let ((wx (wrap nx (send window ':width)))Ť‰ (wy (wrap ny (send window ':height))))Ť‰(send window ':draw-line (fixr xcor) (fixr ycor)Ť‰ (fixr nx) (fixr ny) (pick-alu pen) nil)‰; draw first lineŤ‰(if (or ( nx wx) ( ny wy))Ť‰ (send window ':draw-line (fixr (- wx dx)) (fixr (- wy dy))Ť‰‰ (fixr wx) (fixr wy) (pick-alu pen) nil)))Ť (send window ':tell-turtles ':draw)))ŤŤŤ(defun pick-alu (pen)Ť (selectq penŤ ((t :DOWN :IOR) tv:alu-ior)‰‰‰; T, :DOWN, or :IOR mean inclusive-or.Ť (:XOR tv:alu-xor)‰‰‰‰; :XOR means exclusive-or.Ť (:ERASE tv:alu-andca)‰‰‰; :ERASE means nand.Ť (t 3)))‰‰‰‰‰; anything else means do nothing.ŤŤ;------------------------------------------------------------------------------Ť;Ť; The rest of the standard turtle functions:ŤŤ(defmethod (basic-turtle :backward) (n) (send self ':forward (- n)))ŤŤ(defmethod (basic-turtle :right) (a)Ť (send self ':set-heading (+ heading a)))ŤŤ(defmethod (basic-turtle :left) (a)Ť (send self ':set-heading (- heading a)))ŤŤ(defmethod (basic-turtle :penup) ()Ť (setq pen ':up))ŤŤ(defmethod (basic-turtle :pendown) (&optional (p ':down))Ť (setq pen p))ŤŤ(defmethod (basic-turtle :hide) ()Ť (setq hidden? t)Ť (send self ':erase))ŤŤ(defmethod (basic-turtle :unhide) ()Ť (setq hidden? nil)Ť (send self ':draw))ŤŤ(defmethod (basic-turtle :home) ()Ť (send self ':set-pos (* .5 (send window ':width))Ť‰ (* .5 (send window ':height)))Ť (send self ':set-heading 0))ŤŤ(defmethod (basic-turtle :cs) ()Ť (send window ':refresh))ŤŤ;------------------------------------------------------------------------------Ť;Ť; Here's some shorthand for the same messages:Ť Ť(defmethod (basic-turtle :fd) (n) (send self ':forward n))‰; ForwardŤ(defmethod (basic-turtle :bk) (n) (send self ':forward (- n)))‰; BackwardŤ(defmethod (basic-turtle :rt) (a) (send self ':right a))‰; RightŤ(defmethod (basic-turtle :lt) (a) (send self ':right (- a)))‰; LeftŤ(defmethod (basic-turtle :pu) () (send self ':penup))‰ ; Pen upŤ(defmethod (basic-turtle :pd) (&optional (p ':down))‰ ; Pen downŤ (send self ':pendown p))ŤŤ(compile-flavor-methods basic-turtle)Ť(defvar *turtle-loadedp t)LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 12 :LENGTH-IN-BYTES 12016 :AUTHOR "WILDE" :CREATION-DATE 2725554940 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE" :TYPE "LISP" :VERSION 3) ;;; -*- Package: (ICON); Mode: LISP; Base: 10 -*-Ť;Ť; YATI (Yet another Turtle Implementation)Ť; Copyright 1984, Steve StrassmannŤ;Ť; This software is in the public domain. You may freely distribute itŤ; for educational purposes and incorporate it in other publicŤ; domain software, but it can not be incorporated into a productŤ; and sold without permission from the author.Ť;Ť; To use this file: Ť; No other files need to be loaded. Ť; This provides the basic building blocks for other, neater turtles.Ť;Ť; Experienced logoites will need no introduction; others can justŤ; try loading DEMO-ICON and playing with the turtles.Ť; Ť;------------------------------------------------------------------------------Ť;Ť; This file defines the following flavors:Ť;Ť; BASIC-TURTLE, which acts like a standard LOGO turtleŤ; POND-MIXIN, a window mixin which handles turtles.Ť; Always mix in this flavor to any window which willŤ; have turtles on it.ŤŤ;==============================================================================Ť;Ť; Basic Turtles are things which obey standard LOGO-type turtle commands.Ť; They look like triangles pointed in a certain direction (specified in degrees,Ť; with 0 degrees meaning pointing toward the top of the screen), at a certainŤ; position in the screen.Ť;Ť; You can send them these messages:Ť;Ť; :FORWARD :FD Ť; :BACKWARD :BK Ť; :LEFT :LT Ť; :RIGHT :RT Ť; :PENUP :PUŤ; :PENDOWN [] :PD [] is optional. It defaults to :DOWN (ior).Ť; Others are :IOR, :XOR, :ERASE; :UP, T & NILŤ; :HIDE Makes the turtle invisible.Ť; :UNHIDE Makes the turtle visible.Ť; :HOME Puts turtle in the screen's center, facing up.Ť; :CS Clears the turtle's screen.Ť; :SET-POS Ť; :SET-HEADING Ť; :SET-WINDOW Move the turtle to a new window.Ť;Ť; You can make a turtle with Ť;Ť; (MAKE-TURTLE . )Ť; Window must have POND-MIXIN.Ť; After the window come alternating keywords and valuesŤ; for initializing the turtle. Its position defaults toŤ; the HOME position: center of the pond, facing up.Ť; Ť;==============================================================================Ť;Ť; This is a window which has turtles on itŤ;Ť;Ť; It keeps track of its turtles with the following messages:Ť;Ť; :ADD-TURTLE Ť; :REMOVE-TURTLE Ť; :TELL-TURTLES [ ... ]Ť;Ť;Ť(defflavor pond-mixinŤ‰((turtles nil))Ť‰(tv:graphics-mixin tv:stream-mixin)‰; This stream has nothing to do with ponds.Ť :initable-instance-variables‰‰‰; It's the boring old lispm STREAM mixin.Ť :gettable-instance-variablesŤ :settable-instance-variables)ŤŤ(defmethod (pond-mixin :after :refresh) (&rest ignore)Ť (loop for turtle in turtlesŤ‰do (send turtle ':set-drawn? nil)‰; Inform the turtle it's been erased.Ť‰do (send turtle ':draw)))‰‰; Draw it and make it visible.ŤŤ(defmethod (pond-mixin :add-turtle) (turtle)Ť (setq turtles (cons turtle turtles)))ŤŤ(defmethod (pond-mixin :remove-turtle) (turtle)Ť (setq turtles (remq turtle turtles)))ŤŤ; &REST takes the rest of the arguments and makes a list, ARGS.Ť; Lexpr-funcall unravels its last argument and passes its contentsŤ; to the function being called.Ť; Thus, for example, (lexpr-funcall '+ 1 1 '(1 1)) returns 4.Ť;Ť; You could send a message like (send window ':tell-turtles ':forward 100)Ť; and all the turtles would go forward 100.Ť;Ť(defmethod (pond-mixin :tell-turtles) (message &rest args)Ť (loop for turtle in turtlesŤ‰do (lexpr-funcall turtle message args)))ŤŤŤ;==============================================================================ŤŤŤ(defflavor basic-turtleŤ‰((xcor nil)Ť‰ (ycor nil)Ť‰ (pen ':down)Ť‰ (hidden? nil)‰‰‰‰; Hidden turtles don't want to get drawn.Ť‰ (drawn? nil)‰‰‰‰; Undrawn, non-hidden turtles get drawn.Ť‰ (heading 0)‰‰‰‰; 0 degrees is due North.Ť‰ (height 5)‰‰‰‰; 1/3 height of the turtle's triangle Ť‰ (width 5)‰‰‰‰; 1/2 base of the turtle's triangleŤ‰ (window nil))Ť‰()Ť :initable-instance-variablesŤ :gettable-instance-variablesŤ :settable-instance-variables)ŤŤ; You can make a turtle with (MAKE-TURTLE . )Ť; For example, (SETQ FRED (MAKE-TURTLE *MY-WINDOW ':XCOR 50 ':HEADING 180))Ť;Ť; The window must have POND-MIXIN. After the window come alternatingŤ; keywords and values for initializing the turtle. The turtle's position defaultsŤ; to the HOME position: center of the pond, facing up. (see the :INIT method)Ť;Ť(defmacro make-turtle (window . options)Ť `(make-instance 'basic-turtle ':window ,window . ,options))ŤŤ; SET-POS and SET-HEADING handle going beyond limits so nothing else has to.Ť; The position is in screen coordinates.Ť;Ť(defmethod (basic-turtle :set-pos) (x y)Ť (if (not hidden?) (send self ':erase))Ť (setq xcor (wrap x (send window ':width))Ť‰ycor (wrap y (send window ':height)))Ť (if (not hidden?) (send self ':draw)))ŤŤ; Degrees, not radians. 0 degrees is straight up.Ť;Ť(defmethod (basic-turtle :set-heading) (h)Ť (send self ':erase)Ť (setq heading (wrap h 360))Ť (send self ':draw))ŤŤ; Confines x to the interval 0  x  bound.Ť; Probably faster than modulo, though I never benchmarked it.Ť;Ť(defun wrap (x bound)‰‰‰ Ť (cond ((minusp x) (wrap (+ x bound) bound))Ť‰((> x bound)(wrap (- x bound) bound))Ť‰(t x)))ŤŤ; The three corners of the triangle are rotated relative to the center.Ť; If the turtle were facing north, its corners would have the followingŤ; relative coordinates:Ť; Top x: 0 y: (* 2 height) *Ť; Left x: -width y: -height ***Ť; Right x: width y: -height *****ŤŤ(defmethod (basic-turtle :draw) ()Ť (if (or hidden? drawn?) nil‰ ‰; don't draw hidden or already drawn turtles.Ť (send window ':draw-triangle‰‰‰; draw-triangle takes 7 arguments:Ť‰ (fixr (+ xcor (rotx 0 (* 2 height) heading)))‰; x1Ť‰ (fixr (- ycor (roty 0 (* 2 height) heading)))‰; y1Ť‰ (fixr (+ xcor (rotx (- width) (- height) heading)))‰; x2Ť‰ (fixr (- ycor (roty (- width) (- height) heading)))‰; y2Ť‰ (fixr (+ xcor (rotx width (- height) heading)))‰; x3Ť‰ (fixr (- ycor (roty width (- height) heading)))‰; y3Ť‰ tv:alu-xor) ‰‰‰ ; aluŤ (setq drawn? t)))ŤŤ(defmethod (basic-turtle :erase) ()Ť (if (not drawn?) nil‰‰ ‰; don't erase undrawn turtlesŤ (send window ':draw-triangle‰‰‰; draw-triangle takes 7 arguments:Ť‰ (fixr (+ xcor (rotx 0 (* 2 height) heading)))‰; x1Ť‰ (fixr (- ycor (roty 0 (* 2 height) heading)))‰; y1Ť‰ (fixr (+ xcor (rotx (- width) (- height) heading)))‰; x2Ť‰ (fixr (- ycor (roty (- width) (- height) heading)))‰; y2Ť‰ (fixr (+ xcor (rotx width (- height) heading)))‰; x3Ť‰ (fixr (- ycor (roty width (- height) heading)))‰; y3Ť‰ tv:alu-xor) ‰‰‰ ; aluŤ (setq drawn? nil)))ŤŤŤ; This returns the X-coordinate of the rotated pointŤ;Ť(defun rotx (x y theta)Ť (+ (* x (cosd theta))Ť (* y (sind theta))))ŤŤ; This returns the Y-coordinate of the rotated pointŤ;Ť(defun roty (x y theta)Ť (- (* y (cosd theta))Ť (* x (sind theta))))ŤŤ;------------------------------------------------------------------------------ŤŤ; Let's keep track of every turtle ever created automatically.Ť; The window should have the flavor POND-MIXIN mixed in.Ť;Ť(defmethod (basic-turtle :after :init) (&rest ignore)Ť (if (null window)Ť nil‰‰‰‰‰; Can't do anythingŤ (send window ':add-turtle self)Ť (or xcor (setq xcor (* .5 (send window ':width))))Ť (or ycor (setq ycor (* .5 (send window ':height))))Ť (send self ':draw)))ŤŤ(defmethod (basic-turtle :before :set-window) (ignore)Ť (and window (send window ':remove-turtle self)))ŤŤ(defmethod (basic-turtle :after :set-window) (new-window)Ť (and new-window (send new-window ':add-turtle self)))ŤŤ;------------------------------------------------------------------------------Ť; Go forward (move ahead, whip it, whip it good ......)Ť;Ť(defmethod (basic-turtle :forward) (n)Ť (let* ((dx (* (sind heading) n))Ť‰ (dy (* (cosd heading) -1 n))‰‰; Remember that Y increases downwardsŤ‰ (nx (+ xcor dx))‰‰‰; on the lisp machine....Ť‰ (ny (+ ycor dy)))Ť (send self ':handle-pen dx dy nx ny)Ť (send self ':set-pos nx ny)))ŤŤ; Wraparound is the notion that going off to one side makes you show up on theŤ; other side. Our turtles "wrap" when they try to leave the screen.Ť; :HANDLE-PEN must draw one line if the turtle's movement is totally on-screen,Ť; and two lines if there's wraparound. Clipping (trimming the length of the lines)Ť; isn't necessary, since the lisp machine will merely ignore the part of theŤ; line that lies off-screen. I use the following position variables:Ť;Ť; DX,DY: change in position. NX,NY: unclipped new position. WX,WY: wrapped new position.Ť;Ť; PEN must be bound to a keyword or T or NIL. This tells the turtle what kind ofŤ; line to draw. PICK-ALU decides which kind of alu to use when drawing; for more infoŤ; on alu's, see the Window system manual. These keywords are defined:Ť; :IOR, :XOR, :ERASE, :UP (does nothing), :DOWN (inclusive or).Ť; Also, T means :DOWN and NIL means :UP.Ť;Ť; Note that the turtles are erased. This is kind of like lifting up your feetŤ; before painting the floor; an inaccurate line would be drawn if the turtleŤ; stayed on the screen.Ť;Ť(defmethod (basic-turtle :handle-pen) (dx dy nx ny)Ť (if (or (null pen) (eq pen ':up))Ť nil‰‰‰‰‰; don't draw a line if the pen is up.Ť (send window ':tell-turtles ':erase)Ť (let ((wx (wrap nx (send window ':width)))Ť‰ (wy (wrap ny (send window ':height))))Ť‰(send window ':draw-line (fixr xcor) (fixr ycor)Ť‰ (fixr nx) (fixr ny) (pick-alu pen) nil)‰; draw first lineŤ‰(if (or ( nx wx) ( ny wy))Ť‰ (send window ':draw-line (fixr (- wx dx)) (fixr (- wy dy))Ť‰‰ (fixr wx) (fixr wy) (pick-alu pen) nil)))Ť (send window ':tell-turtles ':draw)))ŤŤŤ(defun pick-alu (pen)Ť (selectq penŤ ((t :DOWN :IOR) tv:alu-ior)‰‰‰; T, :DOWN, or :IOR mean inclusive-or.Ť (:XOR tv:alu-xor)‰‰‰‰; :XOR means exclusive-or.Ť (:ERASE tv:alu-andca)‰‰‰; :ERASE means nand.Ť (t 3)))‰‰‰‰‰; anything else means do nothing.ŤŤ;------------------------------------------------------------------------------Ť;Ť; The rest of the standard turtle functions:ŤŤ(defmethod (basic-turtle :backward) (n) (send self ':forward (- n)))ŤŤ(defmethod (basic-turtle :right) (a)Ť (send self ':set-heading (+ heading a)))ŤŤ(defmethod (basic-turtle :left) (a)Ť (send self ':set-heading (- heading a)))ŤŤ(defmethod (basic-turtle :penup) ()Ť (setq pen ':up))ŤŤ(defmethod (basic-turtle :pendown) (&optional (p ':down))Ť (setq pen p))ŤŤ(defmethod (basic-turtle :hide) ()Ť (setq hidden? t)Ť (send self ':erase))ŤŤ(defmethod (basic-turtle :unhide) ()Ť (setq hidden? nil)Ť (send self ':draw))ŤŤ(defmethod (basic-turtle :home) ()Ť (send self ':set-pos (* .5 (send window ':width))Ť‰ (* .5 (send window ':height)))Ť (send self ':set-heading 0))ŤŤ(defmethod (basic-turtle :cs) ()Ť (send window ':refresh))ŤŤ;------------------------------------------------------------------------------Ť;Ť; Here's some shorthand for the same messages:Ť Ť(defmethod (basic-turtle :fd) (n) (send self ':forward n))‰; ForwardŤ(defmethod (basic-turtle :bk) (n) (send self ':forward (- n)))‰; BackwardŤ(defmethod (basic-turtle :rt) (a) (send self ':right a))‰; RightŤ(defmethod (basic-turtle :lt) (a) (send self ':right (- a)))‰; LeftŤ(defmethod (basic-turtle :pu) () (send self ':penup))‰ ; Pen upŤ(defmethod (basic-turtle :pd) (&optional (p ':down))‰ ; Pen downŤ (send self ':pendown p))ŤŤ(compile-flavor-methods basic-turtle)Ť(defvar *turtle-loadedp t)LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 3 :LENGTH-IN-BYTES 2165 :AUTHOR "WILDE" :CREATION-DATE 2716905366 :QFASLP NIL :LENGTH 2165 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-FRAME-KEY-TOGGLE" :TYPE "TEXT" :VERSION 2) -*- Mode:Text; Fonts:(CPTFONT) -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤŤTitle: Constraint FramesŤSubtitle: Problem solution for toggling configurations byŤ binding a key.ŤFile: none - make changes as below.ŤŤŤTo toggle between configurations add the function change-displayŤand change turtle as below. The changes should be in Ťturtle-constraint-one-config. See turtle-constraint-two-config.ŤŤŤŤ(defun change-display ()ŤŤ "Does the work of toggling between configurations on command.ŤDetermine which configuration is displayed, then go to the otherŤone. Refresh the screen when you are done."ŤŤ (send *turtle-frameŤ‰':set-configurationŤ‰(if (eq (send *turtle-frame ':configuration)Ť‰‰'alternate-configuration)Ť‰ 'standard-configurationŤ‰ 'alternate-configuration))Ť (send *turtle-lake ':refresh))ŤŤŤŤŤŤ; Turtle is the top-level function. It makes the turtle frame,Ť; then runs a loop reading from the io-buffer, and performingŤ; the actions indicated.ŤŤ(defun turtle ()Ť (let* ((*turtle-frame (make-instance 'turtle-frame))Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ :get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ :get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ :get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *turtle-frame :expose)Ť (send *turtle-frame :activate)Ť (send *prompt-pane :select)ŤŤ (setq *turtle (make-turtle *turtle-lake))Ť (send *turtle :pendown)Ť Ť (loop for input = (send *prompt-pane :any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤŤ; Here is where you add conde to intercept keyboard inputŤ; and do special things with defined keys.Ť; Notice that the key "c" has been given the functionalityŤ; of toggling between the two configurations of the turtleŤ; constraint frame.ŤŤ‰‰ (#/c (change-display)) Ť‰‰ (#\end (send *turtle-frame :bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ :execute (second input)))Ť‰‰ (t (beep))))))))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 2 :LENGTH-IN-BYTES 1396 :AUTHOR "WILDE" :CREATION-DATE 2716906250 :QFASLP NIL :LENGTH 1396 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-FRAME-TWO-CONFIG" :TYPE "TEXT" :VERSION 3) -*- Mode:Text; Fonts:(CPTFONT) -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤTitle: Constraint FramesŤSubtitle: Problem solution for adding constraint an alternateŤ configuration to the constraint frame.ŤFile: none - change the turtle-frame in files as indicated-below.ŤŤŤŤTo add an alternate configuration to turtle-frame change Ťturtle-frame in turtle-constraint-one-config to look as below.ŤSee turtle-constraint-two-config.ŤŤŤ(defflavor turtle-frameŤ‰ ()Ť‰ (tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Frame")Ť (:default-init-plistŤ :expose-p t ; expose w/o blink on instantiationŤ :activate-p t ; activate on instantiationŤ :save-bits :delayed ; make save bits array on deexposureŤ :panesŤ '((command-pane turtle-command)Ť (turtle-pane turtle-lake)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ‰(command-pane turtle-pane prompt-pane)Ť‰((command-pane :ask :pane-size)) ; as big as it needsŤ‰((prompt-pane 8 :lines)) ; 8 linesŤ‰((turtle-pane :even))) ; whatever's left overŤ (alternate-configurationŤ‰(turtle-pane command-pane prompt-pane)Ť‰((command-pane :ask :pane-size))Ť‰((prompt-pane 8 :lines))Ť‰((turtle-pane :even))))))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 6 :LENGTH-IN-BYTES 5948 :AUTHOR "WILDE" :CREATION-DATE 2716906333 :QFASLP NIL :LENGTH 5948 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-ONE-CONFIG" :TYPE "LISP" :VERSION 6) ;;; -*- Mode:LISP; Package:ICON; Base:10; Fonts:(CPTFONT) -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤŤ; Title: Constraint FramesŤ; Subtitle: A simple three-pane constraint-frame for turtle.Ť; File: turtle-constraint-one-config.lisp and .qfaslŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle lake pane, and a prompt paneŤ; for prompts and user type-in.ŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤŤ; The turtle frame has one configuration:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom.ŤŤŤ; The following variables are bound in the toplevel function Ť; turtle.ŤŤ(defvar *turtle-frame :unboundŤ "The turtle frame")ŤŤ(defvar *command-pane :unboundŤ "The command pane")ŤŤ(defvar *turtle-lake :unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane :unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle :unboundŤ "The turtle")ŤŤŤ; This is the command pane in the turtle world.ŤŤ(defflavor turtle-commandŤ‰ ()Ť‰ (tv:command-menu)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Command Pane")Ť (:default-init-plistŤ :font-map '(fonts:bigfnt)Ť :columns 4Ť :item-list *command-list))ŤŤ Ť; These are the commands that appear in the command pane.Ť Ť(defvar *command-listŤŤ‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle :set-posŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle :set-headingŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")ŤŤ‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle :draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle :erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle :forwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle :backwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")Ť‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle :rightŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle :leftŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle :penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle :pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle :hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle :unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle :home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake :refresh)Ť‰ :documentation "Clear the turtle pond")ŤŤ‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame :bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŤŤŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.ŤŤ(defflavor turtle-frameŤ‰ ()Ť‰ (tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Frame")Ť (:default-init-plistŤ :expose-p t ; expose w/o blink on instantiationŤ :activate-p t ; activate on instantiationŤ :save-bits :delayed ; make save bits array on deexposureŤ :panesŤ '((command-pane turtle-command)Ť (turtle-pane turtle-lake)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ‰(command-pane turtle-pane prompt-pane)Ť‰((command-pane :ask :pane-size)) ; as big as it needsŤ‰((prompt-pane 8 :lines)) ; 8 linesŤ‰((turtle-pane :even)))))) ; whatever's left overŤŤŤŤ‰ Ť; Turtle is the top-level function. It makes the turtle frame,Ť; then runs a loop reading from the io-buffer, and performingŤ; the actions indicated.ŤŤ(defun turtle ()Ť (let* ((*turtle-frame (make-instance 'turtle-frame))Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ :get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ :get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ :get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *turtle-frame :expose)Ť (send *turtle-frame :activate)Ť (send *prompt-pane :select)Ť Ť (setq *turtle (make-turtle *turtle-lake))Ť (send *turtle :pendown)Ť Ť (loop for input = (send *turtle-lake :any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤ‰‰ (#\end (send *turtle-frame :bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ :execute (second input)))Ť‰‰ (t (beep))))))))Ť‰‰‰ŤŤŤ; Put turtle on system key 1. In order to run turtle, doŤ; 1ŤŤ(tv:add-system-key #\1 '(turtle) "Turtle Pond")LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 6 :LENGTH-IN-BYTES 5950 :AUTHOR "debbie" :CREATION-DATE 2725558008 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-ONE-CONFIG" :TYPE "LISP" :VERSION 7) ;;; -*- Mode:LISP; Package:(ICON); Base:10; Fonts:(CPTFONT) -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤŤ; Title: Constraint FramesŤ; Subtitle: A simple three-pane constraint-frame for turtle.Ť; File: turtle-constraint-one-config.lisp and .qfaslŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle lake pane, and a prompt paneŤ; for prompts and user type-in.ŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤŤ; The turtle frame has one configuration:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom.ŤŤŤ; The following variables are bound in the toplevel function Ť; turtle.ŤŤ(defvar *turtle-frame :unboundŤ "The turtle frame")ŤŤ(defvar *command-pane :unboundŤ "The command pane")ŤŤ(defvar *turtle-lake :unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane :unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle :unboundŤ "The turtle")ŤŤŤ; This is the command pane in the turtle world.ŤŤ(defflavor turtle-commandŤ‰ ()Ť‰ (tv:command-menu)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Command Pane")Ť (:default-init-plistŤ :font-map '(fonts:bigfnt)Ť :columns 4Ť :item-list *command-list))ŤŤ Ť; These are the commands that appear in the command pane.Ť Ť(defvar *command-listŤŤ‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle :set-posŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle :set-headingŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")ŤŤ‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle :draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle :erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle :forwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle :backwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")Ť‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle :rightŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle :leftŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle :penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle :pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle :hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle :unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle :home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake :refresh)Ť‰ :documentation "Clear the turtle pond")ŤŤ‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame :bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŤŤŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.ŤŤ(defflavor turtle-frameŤ‰ ()Ť‰ (tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Frame")Ť (:default-init-plistŤ :expose-p t ; expose w/o blink on instantiationŤ :activate-p t ; activate on instantiationŤ :save-bits :delayed ; make save bits array on deexposureŤ :panesŤ '((command-pane turtle-command)Ť (turtle-pane turtle-lake)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ‰(command-pane turtle-pane prompt-pane)Ť‰((command-pane :ask :pane-size)) ; as big as it needsŤ‰((prompt-pane 8 :lines)) ; 8 linesŤ‰((turtle-pane :even)))))) ; whatever's left overŤŤŤŤ‰ Ť; Turtle is the top-level function. It makes the turtle frame,Ť; then runs a loop reading from the io-buffer, and performingŤ; the actions indicated.ŤŤ(defun turtle ()Ť (let* ((*turtle-frame (make-instance 'turtle-frame))Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ :get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ :get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ :get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *turtle-frame :expose)Ť (send *turtle-frame :activate)Ť (send *prompt-pane :select)Ť Ť (setq *turtle (make-turtle *turtle-lake))Ť (send *turtle :pendown)Ť Ť (loop for input = (send *turtle-lake :any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤ‰‰ (#\end (send *turtle-frame :bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ :execute (second input)))Ť‰‰ (t (beep))))))))Ť‰‰‰ŤŤŤ; Put turtle on system key 1. In order to run turtle, doŤ; 1ŤŤ(tv:add-system-key #\1 '(turtle) "Turtle Pond")LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 5 :LENGTH-IN-BYTES 5088 :AUTHOR "WILDE" :CREATION-DATE 2716905472 :QFASLP NIL :LENGTH 5088 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-ONE-CONFIG-EXERCISE" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Package:ICON; Base:10; Fonts:(CPTFONT) -*-ŤŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; Title: Constraint FramesŤ; Subtitle: A simple three-pane constraint-frame for turtle.Ť; File: turtle-constraint-one-config.lisp and .qfaslŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle lake pane, and a prompt paneŤ; for prompts and user type-in.ŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤŤ; The turtle frame has one configuration:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom.ŤŤŤ; The following variables are bound in the toplevel function Ť; turtle.ŤŤ(defvar *turtle-frame ':unboundŤ "The turtle frame")ŤŤ(defvar *command-pane ':unboundŤ "The command pane")ŤŤ(defvar *turtle-lake ':unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane ':unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle ':unboundŤ "The turtle")ŤŤŤŤ; This is the command pane in the turtle world.ŤŤ; ********** FILL IN THE MISSING CODE **********Ť(defflavor turtle-commandŤŤ‰ )ŤŚ ŤŤŤŤŤŤ; These are the commands that appear in the command pane.Ť Ť(defvar *command-listŤŤ‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle ':set-posŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle ':set-headingŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")ŤŤ‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle ':draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle ':erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle ':forwardŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle ':backwardŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")ŤŚŤŤŤŤŤ‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle ':rightŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle ':leftŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle ':penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle ':pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle ':hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle ':unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle ':home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake ':refresh)Ť‰ :documentation "Clear the turtle pond")ŤŤ‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame ':bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŚŤŤŤŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.ŤŤ; ********** FILL IN THE MISSING CODE **********Ť(defflavor turtle-frameŤŤ‰ )ŤŤ‰ Ť; Turtle is the top-level function. It makes the turtle frame,Ť; then runs a loop reading from the io-buffer, and performingŤ; the actions indicated.ŤŤ(defun turtle ()Ť (let* ((*turtle-frame (make-instance 'turtle-frame))Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ ':get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ ':get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ ':get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *turtle-frame ':expose)Ť (send *turtle-frame ':activate)Ť (send *prompt-pane ':select)Ť Ť (setq *turtle (make-turtle *turtle-lake))Ť (send *turtle ':pendown)Ť Ť (loop for input = (send *turtle-lake ':any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤ‰‰ (#\end (send *turtle-frame ':bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ ':execute (second input)))Ť‰‰ (t (beep))))))))Ť‰‰‰ŤŤŤ; Put turtle on system key 9. In order to run turtle, doŤ; 9ŤŤ; ********** FILL IN THE MISSING CODE **********ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 5 :LENGTH-IN-BYTES 5090 :AUTHOR "debbie" :CREATION-DATE 2725558034 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-ONE-CONFIG-EXERCISE" :TYPE "LISP" :VERSION 2) ;;; -*- Mode:LISP; Package:(ICON); Base:10; Fonts:(CPTFONT) -*-ŤŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; Title: Constraint FramesŤ; Subtitle: A simple three-pane constraint-frame for turtle.Ť; File: turtle-constraint-one-config.lisp and .qfaslŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle lake pane, and a prompt paneŤ; for prompts and user type-in.ŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤŤ; The turtle frame has one configuration:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom.ŤŤŤ; The following variables are bound in the toplevel function Ť; turtle.ŤŤ(defvar *turtle-frame ':unboundŤ "The turtle frame")ŤŤ(defvar *command-pane ':unboundŤ "The command pane")ŤŤ(defvar *turtle-lake ':unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane ':unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle ':unboundŤ "The turtle")ŤŤŤŤ; This is the command pane in the turtle world.ŤŤ; ********** FILL IN THE MISSING CODE **********Ť(defflavor turtle-commandŤŤ‰ )ŤŚ ŤŤŤŤŤŤ; These are the commands that appear in the command pane.Ť Ť(defvar *command-listŤŤ‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle ':set-posŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle ':set-headingŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")ŤŤ‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle ':draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle ':erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle ':forwardŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle ':backwardŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")ŤŚŤŤŤŤŤ‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle ':rightŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle ':leftŤ‰‰ (prompt-and-read ':numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle ':penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle ':pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle ':hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle ':unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle ':home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake ':refresh)Ť‰ :documentation "Clear the turtle pond")ŤŤ‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame ':bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŚŤŤŤŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.ŤŤ; ********** FILL IN THE MISSING CODE **********Ť(defflavor turtle-frameŤŤ‰ )ŤŤ‰ Ť; Turtle is the top-level function. It makes the turtle frame,Ť; then runs a loop reading from the io-buffer, and performingŤ; the actions indicated.ŤŤ(defun turtle ()Ť (let* ((*turtle-frame (make-instance 'turtle-frame))Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ ':get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ ':get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ ':get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *turtle-frame ':expose)Ť (send *turtle-frame ':activate)Ť (send *prompt-pane ':select)Ť Ť (setq *turtle (make-turtle *turtle-lake))Ť (send *turtle ':pendown)Ť Ť (loop for input = (send *turtle-lake ':any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤ‰‰ (#\end (send *turtle-frame ':bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ ':execute (second input)))Ť‰‰ (t (beep))))))))Ť‰‰‰ŤŤŤ; Put turtle on system key 9. In order to run turtle, doŤ; 9ŤŤ; ********** FILL IN THE MISSING CODE **********ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 7 :LENGTH-IN-BYTES 7079 :AUTHOR "WILDE" :CREATION-DATE 2716906414 :QFASLP NIL :LENGTH 7079 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-TWO-CONFIG" :TYPE "LISP" :VERSION 8) ;;; -*- Mode:LISP; Package:ICON; Base:10; Fonts:(CPTFONT) -*-ŤŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; Title: Constraint FramesŤ; Subtitle: A two-configuration constraint frame for turtle.Ť; Problem solution for exercise to add a configurationŤ; to the constraint frame, and toggle with a key.Ť; File: turtle-constraint-two-config.lisp and .qfasl.ŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle pond pane, and a prompt pane Ť; for prompts and user responses.ŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤŤ; The turtle frame has two configurations:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom, andŤŤ; - alternate-configuration, which has the turtle pond on theŤ; top and the command menu on the bottom.ŤŤŤ; The following variables are bound in the toplevel functionŤ; turtle.ŤŤ(defvar *turtle-frame :unboundŤ "The turtle frame")ŤŤ(defvar *command-pane :unboundŤ "The command pane")ŤŤ(defvar *turtle-lake :unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane :unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle :unboundŤ "The turtle")ŤŤŤŤ; This is the command pane in the turtle world.ŤŤ(defflavor turtle-commandŤ‰ ()Ť‰ (tv:command-menu)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Command Pane")Ť (:default-init-plistŤ :font-map '(fonts:bigfnt)Ť :columns 4Ť :item-list *command-list))ŤŤŤŤ; These are the commands that appear in the command pane.ŤŤ(defvar *command-listŤ‰Ť‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle :set-posŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle :set-headingŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle :draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle :erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle :forwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle :backwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")Ť‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle :rightŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle :leftŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle :penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle :pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle :hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle :unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle :home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake :refresh)Ť‰ :documentation "Clear the turtle pond")Ť‰ Ť‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame :bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.Ť; Notice that two configurations are defined.ŤŤ(defflavor turtle-frameŤ‰ ()Ť‰ (tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Frame")Ť (:default-init-plistŤ :expose-p t ; expose w/o blink on instantiationŤ :activate-p t ; activate on instantiationŤ :save-bits :delayed ; make save bits array on deexposureŤ :panesŤ '((command-pane turtle-command)Ť (turtle-pane turtle-lake)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ‰(command-pane turtle-pane prompt-pane)Ť‰((command-pane :ask :pane-size)) ; as big as it needsŤ‰((prompt-pane 8 :lines)) ; 8 linesŤ‰((turtle-pane :even))) ; whatever's left overŤ (alternate-configurationŤ‰(turtle-pane command-pane prompt-pane)Ť‰((command-pane :ask :pane-size))Ť‰((prompt-pane 8 :lines))Ť‰((turtle-pane :even))))))ŤŤŤŤŤŤ(defun change-display ()ŤŤ "Does the work of toggling between configurations on command.ŤDetermine which configuration is displayed, then go to the otherŤone. Refresh the screen when you are done."ŤŤ (send *turtle-frameŤ‰:set-configurationŤ‰(if (eq (send *turtle-frame :configuration)Ť‰‰'alternate-configuration)Ť‰ 'standard-configurationŤ‰ 'alternate-configuration))Ť (send *turtle-lake :refresh))Ť‰ ŤŤ; Turtle is the top-level function. It makes the turtle frame,Ť; then runs a loop reading from the io-buffer, and performingŤ; the actions indicated.ŤŤ(defun turtle ()Ť (let* ((*turtle-frame (make-instance 'turtle-frame))Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ :get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ :get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ :get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *turtle-frame :expose)Ť (send *turtle-frame :activate)Ť (send *prompt-pane :select)ŤŤ (setq *turtle (make-turtle *turtle-lake))Ť (send *turtle :pendown)Ť Ť (loop for input = (send *prompt-pane :any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤŤ; Here is where you add conde to intercept keyboard inputŤ; and do special things with defined keys.Ť; Notice that the key "c" has been given the functionalityŤ; of toggling between the two configurations of the turtleŤ; constraint frame.ŤŤ‰‰ (#/c (change-display)) Ť‰‰ (#\end (send *turtle-frame :bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ :execute (second input)))Ť‰‰ (t (beep))))))))Ť‰‰‰ŤŤŤ; Put turtle on system key 1. In order to run turtle, doŤ; 1ŤŤ(tv:add-system-key #\1 '(turtle) "Turtle Pond")LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 7 :LENGTH-IN-BYTES 7081 :AUTHOR "debbie" :CREATION-DATE 2725558059 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-CONSTRAINT-TWO-CONFIG" :TYPE "LISP" :VERSION 9) ;;; -*- Mode:LISP; Package:(ICON); Base:10; Fonts:(CPTFONT) -*-ŤŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; Title: Constraint FramesŤ; Subtitle: A two-configuration constraint frame for turtle.Ť; Problem solution for exercise to add a configurationŤ; to the constraint frame, and toggle with a key.Ť; File: turtle-constraint-two-config.lisp and .qfasl.ŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle pond pane, and a prompt pane Ť; for prompts and user responses.ŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤŤ; The turtle frame has two configurations:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom, andŤŤ; - alternate-configuration, which has the turtle pond on theŤ; top and the command menu on the bottom.ŤŤŤ; The following variables are bound in the toplevel functionŤ; turtle.ŤŤ(defvar *turtle-frame :unboundŤ "The turtle frame")ŤŤ(defvar *command-pane :unboundŤ "The command pane")ŤŤ(defvar *turtle-lake :unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane :unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle :unboundŤ "The turtle")ŤŤŤŤ; This is the command pane in the turtle world.ŤŤ(defflavor turtle-commandŤ‰ ()Ť‰ (tv:command-menu)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Command Pane")Ť (:default-init-plistŤ :font-map '(fonts:bigfnt)Ť :columns 4Ť :item-list *command-list))ŤŤŤŤ; These are the commands that appear in the command pane.ŤŤ(defvar *command-listŤ‰Ť‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle :set-posŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle :set-headingŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle :draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle :erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle :forwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle :backwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")Ť‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle :rightŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle :leftŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle :penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle :pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle :hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle :unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle :home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake :refresh)Ť‰ :documentation "Clear the turtle pond")Ť‰ Ť‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame :bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.Ť; Notice that two configurations are defined.ŤŤ(defflavor turtle-frameŤ‰ ()Ť‰ (tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Frame")Ť (:default-init-plistŤ :expose-p t ; expose w/o blink on instantiationŤ :activate-p t ; activate on instantiationŤ :save-bits :delayed ; make save bits array on deexposureŤ :panesŤ '((command-pane turtle-command)Ť (turtle-pane turtle-lake)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ‰(command-pane turtle-pane prompt-pane)Ť‰((command-pane :ask :pane-size)) ; as big as it needsŤ‰((prompt-pane 8 :lines)) ; 8 linesŤ‰((turtle-pane :even))) ; whatever's left overŤ (alternate-configurationŤ‰(turtle-pane command-pane prompt-pane)Ť‰((command-pane :ask :pane-size))Ť‰((prompt-pane 8 :lines))Ť‰((turtle-pane :even))))))ŤŤŤŤŤŤ(defun change-display ()ŤŤ "Does the work of toggling between configurations on command.ŤDetermine which configuration is displayed, then go to the otherŤone. Refresh the screen when you are done."ŤŤ (send *turtle-frameŤ‰:set-configurationŤ‰(if (eq (send *turtle-frame :configuration)Ť‰‰'alternate-configuration)Ť‰ 'standard-configurationŤ‰ 'alternate-configuration))Ť (send *turtle-lake :refresh))Ť‰ ŤŤ; Turtle is the top-level function. It makes the turtle frame,Ť; then runs a loop reading from the io-buffer, and performingŤ; the actions indicated.ŤŤ(defun turtle ()Ť (let* ((*turtle-frame (make-instance 'turtle-frame))Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ :get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ :get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ :get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *turtle-frame :expose)Ť (send *turtle-frame :activate)Ť (send *prompt-pane :select)ŤŤ (setq *turtle (make-turtle *turtle-lake))Ť (send *turtle :pendown)Ť Ť (loop for input = (send *prompt-pane :any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤŤ; Here is where you add conde to intercept keyboard inputŤ; and do special things with defined keys.Ť; Notice that the key "c" has been given the functionalityŤ; of toggling between the two configurations of the turtleŤ; constraint frame.ŤŤ‰‰ (#/c (change-display)) Ť‰‰ (#\end (send *turtle-frame :bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ :execute (second input)))Ť‰‰ (t (beep))))))))Ť‰‰‰ŤŤŤ; Put turtle on system key 1. In order to run turtle, doŤ; 1ŤŤ(tv:add-system-key #\1 '(turtle) "Turtle Pond")LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 5 :LENGTH-IN-BYTES 4270 :AUTHOR "WILDE" :CREATION-DATE 2716906511 :QFASLP NIL :LENGTH 4270 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-HACKS" :TYPE "LISP" :VERSION 2) ;;; -*- Mode:LISP; Package:ICON; Fonts:(CPTFONT); Base:10 -*-ŤŤ;; Copyright (C) 1984 LISP Machine, Incorporated.ŤŤŤ(defflavor turtle-pond ((doc))Ť‰ (tv:list-mouse-buttons-mixin pond-mixin tv:window))ŤŤ(defmethod (turtle-pond :set-doc) (d)Ť (setq doc d))ŤŤ(defflavor pond-window ((turtle-list))Ť‰ (tv:process-mixin tv:select-mixinŤ‰ tv:stream-mixinŤ‰ tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variables)ŤŤ(defmethod (turtle-pond :handle-mouse) (&aux bl)Ť (setq bl (tv:mouse-set-blinker-definitionŤ‰ :character 6. 7. :onŤ‰ :set-character 37))Ť (tv:mouse-default-handler self nil)Ť (tv:blinker-set-visibility bl nil))ŤŤ(defmethod (turtle-pond :who-line-documentation-string) ()Ť doc)ŤŤ(defun make-pond-window ()Ť (make-instanceŤ 'pond-windowŤ :process '(manage-pond-window)Ť :panesŤ '((pond turtle-pondŤ‰ :label nil :blinker-p nil)Ť (menu-pane tv:command-menuŤ‰‰ :item-listŤ‰‰ (("Set Speed" :value SPEEDŤ‰‰ :documentationŤ‰‰ "Set the Speed of an exposed Turtle")Ť‰‰ ("Reverse Direction" :value REVERSEŤ‰‰ :documentationŤ‰‰ "Make an exposed Turtle back up")Ť‰‰ ("Turn Left" :value LEFTŤ‰‰ :documentation "Turn an exposed Turtle left")Ť‰‰ ("Turn Right" :value RIGHTŤ‰‰ :documentation "Turn an exposed Turtle right")Ť‰‰ ("Lift Pen" :value LIFTŤ‰‰ :documentation "Lift an exposed Turtle's pen")Ť‰‰ ("Lower Pen" :value LOWERŤ‰‰ :documentationŤ‰‰ "Lower an exposed Turtle's pen")Ť‰‰ ("Make New Turtle" :value CREATEŤ‰‰ :documentationŤ‰‰ "Create a new exposed Turtle at 0,0"))))Ť :constraintsŤ '((main . ((pond menu-pane)Ť‰ ((menu-pane 2 :lines))Ť‰ ((pond :even)))))))ŤŤŤ(defvar *test-var* ())ŤŤ(defun manage-pond-window (window)Ť (do-foreverŤ (handle-clicks window)))ŤŤ(defun handle-clicks (window &aux click)Ť (setq click (send window :any-tyi))Ť (if (not (numberp click))Ť (if (equal (car click)Ť‰‰ :MENU)Ť‰ (selectq (get (cadr click) :VALUE)Ť‰ (CREATEŤ‰ (sendŤ‰ (send window :get-pane 'pond) :set-docŤ‰ "Please indicate where to place the new Turtle")Ť‰ (tv:mouse-warpŤ‰ (// (send tv:mouse-sheet :width) 2)Ť‰ Ť‰ (// (send tv:mouse-sheet :height) 2))Ť‰ (setq click nil)Ť‰ (do ()Ť‰‰ (click)Ť‰ (setq click (send window :any-tyi))Ť‰ (if (numberp click)Ť‰‰ (setq click nil)Ť‰‰ (if (not (equal (car click) :MOUSE-BUTTON))Ť‰‰ (setq click nil))))Ť‰ (push (make-turtleŤ‰‰ (send window :get-pane 'pond)Ť‰‰ :xcor (fourth click)Ť‰‰ :ycor (fifth click))Ť‰‰ (send window :turtle-list))Ť‰ (send (send window :get-pane 'pond) :set-doc nil))Ť‰ (SPEEDŤ‰ (send (choose-turtle window)Ť‰‰ :FORWARD (enter-distance)))Ť‰ (LOWERŤ‰ (send (choose-turtle window) :pd ))Ť‰ (RIGHTŤ‰ (send (choose-turtle window) :right (enter-angle)))Ť‰ (LEFTŤ‰ (send (choose-turtle window) :left (enter-angle)))Ť‰ (LIFTŤ‰ (send (choose-turtle window) :pu))Ť‰ (REVERSEŤ‰ (send (choose-turtle window)Ť‰‰ :BK (enter-distance)))))))ŤŤ(defun choose-turtle (window &aux click turtle (dist 888888888))Ť (send (send window :get-pane 'pond) :set-docŤ‰"Please indicate which Turtle to use")Ť (tv:mouse-warp (// (send tv:mouse-sheet :width) 2)Ť‰‰ (// (send tv:mouse-sheet :height) 2))Ť (setq click nil)Ť (do ()Ť (click)Ť (setq click (send window :any-tyi))Ť (if (numberp click)Ť‰(setq click nil)Ť (if (not (equal (car click) :MOUSE-BUTTON))Ť‰ (setq click nil))))Ť (dolist (turt (send window :turtle-list))Ť (if (< (sqrt (+ (^ (- (fourth click) (send turt :xcor)) 2)Ť‰‰ (^ (- (fifth click) (send turt :ycor)) 2)))Ť‰ dist)Ť‰(setq turtle turtŤ‰ dist (sqrt (+ (^ (- (fourth click)Ť‰‰‰‰ (send turt :xcor)) 2)Ť‰‰‰ (^ (- (fifth click)Ť‰‰‰‰ (send turt :ycor)) 2))))))Ť (send (send window :get-pane 'pond) :set-doc nil)Ť turtle)ŤŤ(defvar *holding-value* 10.)Ť(defvar *holding-angle* 45.)ŤŤ(defun enter-distance ()Ť (let ((ibase 10.) (base 10.))Ť (tv:choose-variable-valuesŤ '((*holding-value* "Distance to move" :number)))Ť *holding-value*))ŤŤ(defun enter-angle ()Ť (let ((ibase 10.) (base 10.))Ť (tv:choose-variable-valuesŤ '((*holding-angle* "Angle" :number)))Ť *holding-angle*))ŤŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 5 :LENGTH-IN-BYTES 4272 :AUTHOR "debbie" :CREATION-DATE 2725558092 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-HACKS" :TYPE "LISP" :VERSION 3) ;;; -*- Mode:LISP; Package:(ICON); Fonts:(CPTFONT); Base:10 -*-ŤŤ;; Copyright (C) 1984 LISP Machine, Incorporated.ŤŤŤ(defflavor turtle-pond ((doc))Ť‰ (tv:list-mouse-buttons-mixin pond-mixin tv:window))ŤŤ(defmethod (turtle-pond :set-doc) (d)Ť (setq doc d))ŤŤ(defflavor pond-window ((turtle-list))Ť‰ (tv:process-mixin tv:select-mixinŤ‰ tv:stream-mixinŤ‰ tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variables)ŤŤ(defmethod (turtle-pond :handle-mouse) (&aux bl)Ť (setq bl (tv:mouse-set-blinker-definitionŤ‰ :character 6. 7. :onŤ‰ :set-character 37))Ť (tv:mouse-default-handler self nil)Ť (tv:blinker-set-visibility bl nil))ŤŤ(defmethod (turtle-pond :who-line-documentation-string) ()Ť doc)ŤŤ(defun make-pond-window ()Ť (make-instanceŤ 'pond-windowŤ :process '(manage-pond-window)Ť :panesŤ '((pond turtle-pondŤ‰ :label nil :blinker-p nil)Ť (menu-pane tv:command-menuŤ‰‰ :item-listŤ‰‰ (("Set Speed" :value SPEEDŤ‰‰ :documentationŤ‰‰ "Set the Speed of an exposed Turtle")Ť‰‰ ("Reverse Direction" :value REVERSEŤ‰‰ :documentationŤ‰‰ "Make an exposed Turtle back up")Ť‰‰ ("Turn Left" :value LEFTŤ‰‰ :documentation "Turn an exposed Turtle left")Ť‰‰ ("Turn Right" :value RIGHTŤ‰‰ :documentation "Turn an exposed Turtle right")Ť‰‰ ("Lift Pen" :value LIFTŤ‰‰ :documentation "Lift an exposed Turtle's pen")Ť‰‰ ("Lower Pen" :value LOWERŤ‰‰ :documentationŤ‰‰ "Lower an exposed Turtle's pen")Ť‰‰ ("Make New Turtle" :value CREATEŤ‰‰ :documentationŤ‰‰ "Create a new exposed Turtle at 0,0"))))Ť :constraintsŤ '((main . ((pond menu-pane)Ť‰ ((menu-pane 2 :lines))Ť‰ ((pond :even)))))))ŤŤŤ(defvar *test-var* ())ŤŤ(defun manage-pond-window (window)Ť (do-foreverŤ (handle-clicks window)))ŤŤ(defun handle-clicks (window &aux click)Ť (setq click (send window :any-tyi))Ť (if (not (numberp click))Ť (if (equal (car click)Ť‰‰ :MENU)Ť‰ (selectq (get (cadr click) :VALUE)Ť‰ (CREATEŤ‰ (sendŤ‰ (send window :get-pane 'pond) :set-docŤ‰ "Please indicate where to place the new Turtle")Ť‰ (tv:mouse-warpŤ‰ (// (send tv:mouse-sheet :width) 2)Ť‰ Ť‰ (// (send tv:mouse-sheet :height) 2))Ť‰ (setq click nil)Ť‰ (do ()Ť‰‰ (click)Ť‰ (setq click (send window :any-tyi))Ť‰ (if (numberp click)Ť‰‰ (setq click nil)Ť‰‰ (if (not (equal (car click) :MOUSE-BUTTON))Ť‰‰ (setq click nil))))Ť‰ (push (make-turtleŤ‰‰ (send window :get-pane 'pond)Ť‰‰ :xcor (fourth click)Ť‰‰ :ycor (fifth click))Ť‰‰ (send window :turtle-list))Ť‰ (send (send window :get-pane 'pond) :set-doc nil))Ť‰ (SPEEDŤ‰ (send (choose-turtle window)Ť‰‰ :FORWARD (enter-distance)))Ť‰ (LOWERŤ‰ (send (choose-turtle window) :pd ))Ť‰ (RIGHTŤ‰ (send (choose-turtle window) :right (enter-angle)))Ť‰ (LEFTŤ‰ (send (choose-turtle window) :left (enter-angle)))Ť‰ (LIFTŤ‰ (send (choose-turtle window) :pu))Ť‰ (REVERSEŤ‰ (send (choose-turtle window)Ť‰‰ :BK (enter-distance)))))))ŤŤ(defun choose-turtle (window &aux click turtle (dist 888888888))Ť (send (send window :get-pane 'pond) :set-docŤ‰"Please indicate which Turtle to use")Ť (tv:mouse-warp (// (send tv:mouse-sheet :width) 2)Ť‰‰ (// (send tv:mouse-sheet :height) 2))Ť (setq click nil)Ť (do ()Ť (click)Ť (setq click (send window :any-tyi))Ť (if (numberp click)Ť‰(setq click nil)Ť (if (not (equal (car click) :MOUSE-BUTTON))Ť‰ (setq click nil))))Ť (dolist (turt (send window :turtle-list))Ť (if (< (sqrt (+ (^ (- (fourth click) (send turt :xcor)) 2)Ť‰‰ (^ (- (fifth click) (send turt :ycor)) 2)))Ť‰ dist)Ť‰(setq turtle turtŤ‰ dist (sqrt (+ (^ (- (fourth click)Ť‰‰‰‰ (send turt :xcor)) 2)Ť‰‰‰ (^ (- (fifth click)Ť‰‰‰‰ (send turt :ycor)) 2))))))Ť (send (send window :get-pane 'pond) :set-doc nil)Ť turtle)ŤŤ(defvar *holding-value* 10.)Ť(defvar *holding-angle* 45.)ŤŤ(defun enter-distance ()Ť (let ((ibase 10.) (base 10.))Ť (tv:choose-variable-valuesŤ '((*holding-value* "Distance to move" :number)))Ť *holding-value*))ŤŤ(defun enter-angle ()Ť (let ((ibase 10.) (base 10.))Ť (tv:choose-variable-valuesŤ '((*holding-angle* "Angle" :number)))Ť *holding-angle*))ŤŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 2 :LENGTH-IN-BYTES 1548 :AUTHOR "WILDE" :CREATION-DATE 2716906555 :QFASLP NIL :LENGTH 1548 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-POND" :TYPE "LISP" :VERSION 2) ;;; -*- Mode:LISP; Package:ICON; Base:10 -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ;;; Load this file after TURTLE.LISP to initialize a window (*MY-POND*)Ť;;; for making turtlesŤŤ;;; To use this new window effectively, execute the following sequence:Ť;;; (icon:start-turtle) -> gets you into a new lisp listenerŤ;;; with a pond mixinŤ;;; (pkg-goto 'icon) -> sets the package to iconŤ;;; You are then ready to create turtles.Ť;;; A turtle is made with:Ť;;; (MAKE-TURTLE . )Ť;;; For example:Ť;;; (SETQ TOM (MAKE-TURTLE *MY-POND* :HEADING 180))Ť;;; Remember to send a pen down message the first time a turtle isŤ;;; created. For example:Ť;;; (SEND TOM :PD)Ť;;; Now you are ready to play with moving the turtles. For example:Ť;;; (SEND TOM :FD 50)ŤŤŤ(defvar *my-pond* () "The window in which the turtles live")ŤŤŤ;;; POND is a window with a pond mixin that can handle turtles Ť(defflavor pondŤ‰ ()Ť‰ (pond-mixin tv:lisp-listener))Ť ŤŤ;;; Function START-TURTLE creates an instance of a pond (*MY-POND*)Ť;;; that is ready to accept turtles. Ť(defun start-turtle ()Ť "Creates a window for drawing turtles."Ť (cond (*my-pond*Ť‰ (send *my-pond* :select)Ť‰ *my-pond*)Ť‰(t (setq *my-pond* (make-instance 'pond))Ť‰ (send *my-pond* :select))))ŤŤŤŤ;;; Function SPIRAL is an example of turtle movement.Ť(defun spiral (turtle)Ť "Moves the turtle in a spiral."Ť (loop for size from 1 to 100Ť‰do (send turtle :fd size)Ť‰ (send turtle :rt 112.)))LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 2 :LENGTH-IN-BYTES 1550 :AUTHOR "debbie" :CREATION-DATE 2725558114 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-POND" :TYPE "LISP" :VERSION 3) ;;; -*- Mode:LISP; Package:(ICON); Base:10 -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ;;; Load this file after TURTLE.LISP to initialize a window (*MY-POND*)Ť;;; for making turtlesŤŤ;;; To use this new window effectively, execute the following sequence:Ť;;; (icon:start-turtle) -> gets you into a new lisp listenerŤ;;; with a pond mixinŤ;;; (pkg-goto 'icon) -> sets the package to iconŤ;;; You are then ready to create turtles.Ť;;; A turtle is made with:Ť;;; (MAKE-TURTLE . )Ť;;; For example:Ť;;; (SETQ TOM (MAKE-TURTLE *MY-POND* :HEADING 180))Ť;;; Remember to send a pen down message the first time a turtle isŤ;;; created. For example:Ť;;; (SEND TOM :PD)Ť;;; Now you are ready to play with moving the turtles. For example:Ť;;; (SEND TOM :FD 50)ŤŤŤ(defvar *my-pond* () "The window in which the turtles live")ŤŤŤ;;; POND is a window with a pond mixin that can handle turtles Ť(defflavor pondŤ‰ ()Ť‰ (pond-mixin tv:lisp-listener))Ť ŤŤ;;; Function START-TURTLE creates an instance of a pond (*MY-POND*)Ť;;; that is ready to accept turtles. Ť(defun start-turtle ()Ť "Creates a window for drawing turtles."Ť (cond (*my-pond*Ť‰ (send *my-pond* :select)Ť‰ *my-pond*)Ť‰(t (setq *my-pond* (make-instance 'pond))Ť‰ (send *my-pond* :select))))ŤŤŤŤ;;; Function SPIRAL is an example of turtle movement.Ť(defun spiral (turtle)Ť "Moves the turtle in a spiral."Ť (loop for size from 1 to 100Ť‰do (send turtle :fd size)Ť‰ (send turtle :rt 112.)))LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 8 :LENGTH-IN-BYTES 7732 :AUTHOR "WILDE" :CREATION-DATE 2716906632 :QFASLP NIL :LENGTH 7732 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-PROCESS" :TYPE "LISP" :VERSION 3) ;;; -*- Mode:LISP; Package:ICON; Base:10; Fonts:(CPTFONT) -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; Title: ProcessesŤ; Subtitle: Turtle as a process.Ť; File: turtle-process.lisp and .qfaslŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle pond pane, and a prompt paneŤ; for prompts and user responses.ŤŤ; The constraint frame has an init option of :process,Ť; which sets up a process when the window is instantiated.Ť; the function turtle-initial-function is the initial function,Ť; and it is given the window as an argument. Ť; Turtle-initial-function now does most of the work done by Ť; the function turtle in previous versions.ŤŤ; The function turtle now just creates and returns the Ť; constraint frame.ŤŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤ; The turtle frame has two configurations:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom, andŤŤ; - alternate-configuration, which has the turtle pond on theŤ; top and the command menu on the bottom.ŤŤŤ; The following variables are bound in the toplevel functionŤ; turtle-initial-function.ŤŤ(defvar *turtle-frame :unboundŤ "The turtle frame")ŤŤ(defvar *command-pane :unboundŤ "The command pane")ŤŤ(defvar *turtle-lake :unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane :unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle :unboundŤ "The turtle")ŤŤŤŤ; This is the command pane in the turtle world.ŤŤ(defflavor turtle-commandŤ‰ ()Ť‰ (tv:command-menu)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Command Pane")Ť (:default-init-plistŤ :font-map '(fonts:bigfnt)Ť :columns 4Ť :item-list *command-list))ŤŤŤŤ; These are the commands that appear in the command pane.ŤŤ(defvar *command-listŤ‰Ť‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle :set-posŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle :set-headingŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle :draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle :erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle :forwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle :backwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")Ť‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle :rightŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle :leftŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle :penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle :pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle :hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle :unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle :home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake :refresh)Ť‰ :documentation "Clear the turtle pond")Ť‰ Ť‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame :bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.Ť; Notice that two configurations are defined, and thatŤ; the frame has a :process init option, with Ť; turtle-initial-function as the initial function.ŤŤ(defflavor turtle-frameŤ‰ ()Ť‰ (tv:process-mixinŤ‰ tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Frame")Ť (:default-init-plistŤ :expose-p t ; expose w/o blink on instantiationŤ :activate-p t ; activate on instantiationŤ :save-bits :delayed ; make save bits array on deexposureŤ :process '(turtle-initial-function)Ť :panesŤ '((command-pane turtle-command)Ť (turtle-pane turtle-lake)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ‰(command-pane turtle-pane prompt-pane)Ť‰((command-pane :ask :pane-size)) ; as big as it needsŤ‰((prompt-pane 8 :lines)) ; 8 linesŤ‰((turtle-pane :even))) ; whatever's left overŤ (alternate-configurationŤ‰(turtle-pane command-pane prompt-pane)Ť‰((command-pane :ask :pane-size))Ť‰((prompt-pane 8 :lines))Ť‰((turtle-pane :even))))))ŤŤŤŤŤŤ(defun change-display ()ŤŤ "Does the work of toggling between configurations on command.ŤDetermine which configuration is displayed, then go to the otherŤone. Refresh the screen when you are done."ŤŤ (send *turtle-frameŤ‰:set-configurationŤ‰(if (eq (send *turtle-frame :configuration)Ť‰‰'alternate-configuration)Ť‰ 'standard-configurationŤ‰ 'alternate-configuration))Ť (send *turtle-lake :refresh))Ť‰ ŤŤŤ; Turtle-initial-function is the function called when Ť; turtle-frame is instantiated by the function turtle. Ť; Turtle-initial-function has a single argument - the Ť; instantiated window. Ť; The function turtle is called when you do 1.ŤŤŤ(defun turtle-initial-function (window)Ť (let* ((*turtle-frame window)Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ :get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ :get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ :get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *prompt-pane :select)ŤŤ (setq *turtle (make-turtle *turtle-lake))Ť Ť (loop for input = (send *prompt-pane :any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤŤ; Here is where you add code to intercept keyboard inputŤ; and do special things with defined keys.Ť; Notice that the key "c" has been given the functionalityŤ; of toggling between the two configurations of the turtleŤ; constraint frame.ŤŤ‰‰ (#/c (change-display))Ť‰‰ (#\end (send *turtle-frame :bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ :execute (second input)))Ť‰‰ (t (beep))))))))ŤŤŤ; Turtle creates and returns an instance of turtle-frame.ŤŤ(defun turtle ()Ť (setq *turtle-frame (make-instance 'turtle-frame))Ť (send *turtle-frame :activate)Ť (send *turtle-frame :expose)Ť (tv:await-window-exposure)Ť *turtle-frame)ŤŤŤ; Put turtle on system key 1. In order to run turtle, doŤ; 1Ť Ť(tv:add-system-key #\1 '(turtle) "Turtle Lake")LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 8 :LENGTH-IN-BYTES 7734 :AUTHOR "debbie" :CREATION-DATE 2725558132 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "TURTLE-PROCESS" :TYPE "LISP" :VERSION 4) ;;; -*- Mode:LISP; Package:(ICON); Base:10; Fonts:(CPTFONT) -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; Title: ProcessesŤ; Subtitle: Turtle as a process.Ť; File: turtle-process.lisp and .qfaslŤŤŤ; To run, load the file turtle.qfasl, load this file, then doŤ; 1.ŤŤŤ; This file sets up a constraint frame for turtle consistingŤ; of a command pane, a turtle pond pane, and a prompt paneŤ; for prompts and user responses.ŤŤ; The constraint frame has an init option of :process,Ť; which sets up a process when the window is instantiated.Ť; the function turtle-initial-function is the initial function,Ť; and it is given the window as an argument. Ť; Turtle-initial-function now does most of the work done by Ť; the function turtle in previous versions.ŤŤ; The function turtle now just creates and returns the Ť; constraint frame.ŤŤŤ; We are dealing with only one turtle here, although the code Ť; in turtle is capable of making and handling more.ŤŤ; The turtle frame has two configurations:ŤŤ; - standard-configuration, which has the command menu onŤ; top and the turtle pond on the bottom, andŤŤ; - alternate-configuration, which has the turtle pond on theŤ; top and the command menu on the bottom.ŤŤŤ; The following variables are bound in the toplevel functionŤ; turtle-initial-function.ŤŤ(defvar *turtle-frame :unboundŤ "The turtle frame")ŤŤ(defvar *command-pane :unboundŤ "The command pane")ŤŤ(defvar *turtle-lake :unboundŤ "The turtle pond")ŤŤ(defvar *prompt-pane :unboundŤ "An interaction and prompting pane")ŤŤ(defvar *turtle :unboundŤ "The turtle")ŤŤŤŤ; This is the command pane in the turtle world.ŤŤ(defflavor turtle-commandŤ‰ ()Ť‰ (tv:command-menu)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Command Pane")Ť (:default-init-plistŤ :font-map '(fonts:bigfnt)Ť :columns 4Ť :item-list *command-list))ŤŤŤŤ; These are the commands that appear in the command pane.ŤŤ(defvar *command-listŤ‰Ť‰'(("Set Position"Ť‰ :evalŤ‰ (send *turtle :set-posŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter x pos in pixels: ")Ť‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter y pos in pixels: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Set Heading"Ť‰ :evalŤ‰ (send *turtle :set-headingŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "Enter heading in degrees: "))Ť‰ :documentation "Set the turtle's position")Ť‰ Ť‰ ("Draw Turtle"Ť‰ :evalŤ‰ (send *turtle :draw)Ť‰ :documentation "Draw the turtle in the pond")Ť‰ Ť‰ ("Erase Turtle"Ť‰ :evalŤ‰ (send *turtle :erase)Ť‰ :documentation "Erase the turtle")Ť‰ Ť‰ ("Move Forward"Ť‰ :evalŤ‰ (send *turtle :forwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle forward")Ť‰ Ť‰ ("Move Backward"Ť‰ :evalŤ‰ (send *turtle :backwardŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many pixels? "))Ť‰ :documentation "Move the turtle backwards")Ť‰ Ť‰ ("Turn Right"Ť‰ :evalŤ‰ (send *turtle :rightŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a right turn")Ť‰ Ť‰ ("Turn Left"Ť‰ :evalŤ‰ (send *turtle :leftŤ‰‰ (prompt-and-read :numberŤ‰‰‰‰ "How many degrees? "))Ť‰ :documentation "Take a left turn")Ť‰ Ť‰ ("Pen Up"Ť‰ :evalŤ‰ (send *turtle :penup)Ť‰ :documentation "Lift up the pen")Ť‰ Ť‰ ("Pen Down"Ť‰ :evalŤ‰ (send *turtle :pendown)Ť‰ :documentation "Put the pen to paper")Ť‰ Ť‰ ("Hide"Ť‰ :evalŤ‰ (send *turtle :hide)Ť‰ :documentation "Hide the turtle")Ť‰ Ť‰ ("Unhide"Ť‰ :evalŤ‰ (send *turtle :unhide)Ť‰ :documentation "Unhide the turtle")Ť‰ Ť‰ ("Go Home"Ť‰ :evalŤ‰ (send *turtle :home)Ť‰ :documentation "Send the turtle home")Ť‰ Ť‰ ("Clear Screen"Ť‰ :evalŤ‰ (send *turtle-lake :refresh)Ť‰ :documentation "Clear the turtle pond")Ť‰ Ť‰ ("Exit"Ť‰ :evalŤ‰ (send *turtle-frame :bury)Ť‰ :documentationŤ‰ "Leave the pond")))ŤŤŤŤ; This is a small lake for the turtle to live in.Ť; Notice that it has pond-mixin as a component flavor.ŤŤ(defflavor turtle-lakeŤ‰ ()Ť‰ (pond-mixin tv:window)Ť (:documentationŤ "Turtle pond")Ť (:default-init-plistŤ :save-bits tŤ :label "Turtle Pond")Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variables)ŤŤŤŤ; Define a prompt pane for prompts and user interaction.ŤŤ(defflavor prompt-paneŤ‰ ()Ť‰ (tv:pane-mixin tv:window))ŤŤŤŤ; The turtle frame ties it all together.Ť; Notice that two configurations are defined, and thatŤ; the frame has a :process init option, with Ť; turtle-initial-function as the initial function.ŤŤ(defflavor turtle-frameŤ‰ ()Ť‰ (tv:process-mixinŤ‰ tv:bordered-constraint-frame-with-shared-io-buffer)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:documentationŤ "Turtle Frame")Ť (:default-init-plistŤ :expose-p t ; expose w/o blink on instantiationŤ :activate-p t ; activate on instantiationŤ :save-bits :delayed ; make save bits array on deexposureŤ :process '(turtle-initial-function)Ť :panesŤ '((command-pane turtle-command)Ť (turtle-pane turtle-lake)Ť (prompt-pane prompt-pane))Ť :constraintsŤ '((standard-configurationŤ‰(command-pane turtle-pane prompt-pane)Ť‰((command-pane :ask :pane-size)) ; as big as it needsŤ‰((prompt-pane 8 :lines)) ; 8 linesŤ‰((turtle-pane :even))) ; whatever's left overŤ (alternate-configurationŤ‰(turtle-pane command-pane prompt-pane)Ť‰((command-pane :ask :pane-size))Ť‰((prompt-pane 8 :lines))Ť‰((turtle-pane :even))))))ŤŤŤŤŤŤ(defun change-display ()ŤŤ "Does the work of toggling between configurations on command.ŤDetermine which configuration is displayed, then go to the otherŤone. Refresh the screen when you are done."ŤŤ (send *turtle-frameŤ‰:set-configurationŤ‰(if (eq (send *turtle-frame :configuration)Ť‰‰'alternate-configuration)Ť‰ 'standard-configurationŤ‰ 'alternate-configuration))Ť (send *turtle-lake :refresh))Ť‰ ŤŤŤ; Turtle-initial-function is the function called when Ť; turtle-frame is instantiated by the function turtle. Ť; Turtle-initial-function has a single argument - the Ť; instantiated window. Ť; The function turtle is called when you do 1.ŤŤŤ(defun turtle-initial-function (window)Ť (let* ((*turtle-frame window)Ť‰ (*command-pane (send *turtle-frameŤ‰‰‰ :get-pane 'command-pane))Ť‰ (*turtle-lake (send *turtle-frameŤ‰‰‰ :get-pane 'turtle-pane))Ť‰ (*prompt-pane (send *turtle-frameŤ‰‰‰ :get-pane 'prompt-pane))Ť‰ (base 10.)Ť‰ (ibase 10.)Ť‰ (terminal-io *prompt-pane)Ť‰ (query-io *prompt-pane)Ť‰ (error-output *prompt-pane)Ť‰ *turtle)Ť Ť (send *prompt-pane :select)ŤŤ (setq *turtle (make-turtle *turtle-lake))Ť Ť (loop for input = (send *prompt-pane :any-tyi)Ť‰ do (cond ((atom input)Ť‰‰ (selectq inputŤŤ; Here is where you add code to intercept keyboard inputŤ; and do special things with defined keys.Ť; Notice that the key "c" has been given the functionalityŤ; of toggling between the two configurations of the turtleŤ; constraint frame.ŤŤ‰‰ (#/c (change-display))Ť‰‰ (#\end (send *turtle-frame :bury))Ť‰‰ (t (beep))))Ť‰‰ ((listp input)Ť‰‰ (selectq (car input)Ť‰‰ (:menuŤ‰‰ (send (fourth input)Ť‰‰‰ :execute (second input)))Ť‰‰ (t (beep))))))))ŤŤŤ; Turtle creates and returns an instance of turtle-frame.ŤŤ(defun turtle ()Ť (setq *turtle-frame (make-instance 'turtle-frame))Ť (send *turtle-frame :activate)Ť (send *turtle-frame :expose)Ť (tv:await-window-exposure)Ť *turtle-frame)ŤŤŤ; Put turtle on system key 1. In order to run turtle, doŤ; 1Ť Ť(tv:add-system-key #\1 '(turtle) "Turtle Lake")LMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 6 :LENGTH-IN-BYTES 5557 :AUTHOR "SAM" :CREATION-DATE 2720047942 :QFASLP NIL :LENGTH 5557 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "UNIFICATION" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;UNIFICATIONŤŤ(require 'pattern-definition)Ť(require 'variable-substitution)Ť(provide 'unification)ŤŤŤ#|ŤŤA pattern may be defined as a binary external tree with variables. ForŤexample, a predicate-calculus formula in implicit-quantifier form,Ťexpressed in list notation, can be taken to be a pattern. Notice thatŤnested and dotted lists are fair game.ŤŤA substitution is a table of variables and their corresponding values inŤthe context of that substitution.ŤŤA unifier, if any, of two patterns in the context of a substitution is anŤextension of the given substitution which when applied to the patterns,Ťreplacing variables with their values, results in equivalent patterns.ŤŤA most general unifier (MGU), if any, of two patterns is a smallest unifierŤin the context of an empty substitution. That is, each variable has aŤvalue only if needed to make the patterns equivalent.ŤŤ|#ŤŤŤ(defun unify? (pat1 pat2 &optional (substitution (make-substitution)))Ť "Return a unifier, if any, of patterns PAT1 and PAT2 by extending a givenŤ non-NIL SUBSTITUTION. If SUBSTITUTION is NIL, we return NIL. If noŤ substitution is given, we return a most general unifier, if any."Ť (if substitution (unifier? pat1 pat2 substitution)))ŤŤ(defmacro mgu? (pat1 pat2)Ť "Return a most general unifier, if any, of patterns PAT1 and PAT2."Ť `(unifier? ,pat1 ,pat2 (make-substitution)))ŤŚ#|ŤA UNIFICATION ALGORITHMŤŤŤTo unify two patterns given a non-NIL (but possibly empty) substitution:ŤŤ If the patterns are identical:ŤŤ Return the substitution.ŤŤ Else if either pattern is a bound variable:ŤŤ Unify that variable's ultimate value with the other pattern given theŤ same substitution.ŤŤ Else if either pattern is an unbound variable:ŤŤ If that variable does not occur in the other pattern:ŤŤ Then return the substitution extended by adding that variable withŤ the other pattern as its value.ŤŤ Else return NIL (failure to unify).ŤŤ Else if either pattern is a constant:ŤŤ If that constant equals the other pattern:ŤŤ Then return the substitution.ŤŤ Else return NIL.ŤŤ Else:ŤŤ Unify the first components of the patterns given the sameŤ substitution. If the result is a non-NIL substitution:ŤŤ Then unify the remainders of the patterns given the newŤ substitution.ŤŤ Else return NIL.ŤŤŤAn unbound variable occurs in a pattern given a substitution iff:ŤŤ The variable is identical to the pattern; ORŤŤ The pattern is a bound variable and the unbound variable occurs in theŤ bound variable's ultimate value; ORŤŤ The pattern is a composite and the variable occurs in either theŤ pattern's first component or the remainder of the pattern.ŤŤŤThe following code is a slight variant of this algorithm.Ť|#ŚŤ(defun unifier? (pat1 pat2 substitution)Ť "Return a unifier, if any, of patterns PAT1 and PAT2 by extending a givenŤ non-NIL SUBSTITUTION."Ť (if (variable-p pat1) (setq pat1 (get-ultimate-value pat1 substitution)))Ť (if (variable-p pat2) (setq pat2 (get-ultimate-value pat2 substitution)))Ť (cond ((eq pat1 pat2) substitution)Ť‰((variable-p pat1) (unify-variable? pat1 pat2 substitution))Ť‰((variable-p pat2) (unify-variable? pat2 pat1 substitution))Ť‰((constant-p pat1) (unify-constant? pat1 pat2 substitution))Ť‰((constant-p pat2) nil)Ť;recur-‰((let ((s (unifier? (next-component pat1)Ť;sive‰‰‰ (next-component pat2) substitution)))Ť;ver-‰ (if s (unifier? (rest-of-components pat1)Ť;sion‰‰‰ (rest-of-components pat2) s))))Ť‰((do* ((s substitution (or (unifier? (next-component p1)Ť‰‰‰‰‰ (next-component p2) s)Ť‰‰‰‰ (return nil)))Ť‰ (p1 pat1 (rest-of-components p1))Ť‰ (p2 pat2 (rest-of-components p2)))Ť‰ ((or (eq p1 p2) (atomic-p p1) (atomic-p p2))Ť‰ (unifier? p1 p2 s))))Ť‰))ŤŤ(defun unify-constant? (constant other-pat-not-a-variable substitution)Ť "Unify CONSTANT with another (not EQ) pattern, where the other pattern isŤ not a variable and SUBSTITUTION is non-NIL. The resulting SUBSTITUTION,Ť if any, is returned."Ť (if (match-constant-p constant other-pat-not-a-variable) substitution))ŤŤ(defun unify-variable? (unbound-var other-pattern substitution)Ť "Unify UNBOUND-VAR with another (not EQ) pattern, given a non-NILŤ SUBSTITUTION. The resulting SUBSTITUTION, if any, is returned."Ť (if (and (not (occurs-in-p unbound-var other-pattern substitution))Ť‰ (match-variable-p unbound-var other-pattern))Ť (add-binding-pair unbound-var other-pattern substitution)))ŤŤ(defun occurs-in-p (unbound-var pattern substitution)Ť "Does UNBOUND-VAR occur in PATTERN, given a non-NIL substitution?"Ť (cond ((eq unbound-var pattern))Ť‰((constant-p pattern) nil)Ť‰((variable-p pattern)Ť‰ (let ((value-pat (get-ultimate-value pattern substitution)))Ť‰ (if (not (eq value-pat pattern))Ť‰ (occurs-in-p unbound-var value-pat substitution))))Ť;recur-‰((or (occurs-in-p unbound-var (next-component pattern)Ť;sive‰‰‰‰ substitution)Ť;ver-‰ (occurs-in-p unbound-var (rest-of-components pattern)Ť;sion‰‰‰‰ substitution)))Ť‰((do ((p pattern (rest-of-components p)))Ť‰ ((atomic-p p) (occurs-in-p unbound-var p substitution))Ť‰ (if (occurs-in-p unbound-var (next-component p) substitution)Ť‰ (return t))))Ť‰))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 4 :LENGTH-IN-BYTES 4053 :AUTHOR "SAM" :CREATION-DATE 2720040962 :QFASLP NIL :LENGTH 4053 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "VARIABLE-SUBSTITUTION" :TYPE "LISP" :VERSION 1) ;;; -*- Mode:LISP; Readtable:COMMON-LISP; Base:10 -*-Ť#|ŤŤ (C) COPYRIGHT 1986 LISP Machine, IncorporatedŤ All Rights ReservedŤŤ___________________________________________________________________________Ť|#ŤŤ;;; Samuel F. PilatoŤŤŤŤ;;;;VARIABLE SUBSTITUTIONŤŤ(provide 'variable-substitution)ŤŤŤ;;; A SUBSTITUTION is a set of VARIABLE - VALUE pairs. Each pair indicatesŤ;;; that, in the context of this substitution, the variable is BOUND to theŤ;;; associated value. Even an empty substitution is non-NIL.ŤŤ(defmacro make-binding-pair (variable value) `(cons ,variable ,value))Ť(defmacro binding-variable (binding-pair) `(car ,binding-pair))Ť(defmacro binding-value (binding-pair) `(cdr ,binding-pair))ŤŤ(defmacro make-substitution () `(ncons nil))ŤŤ(defmacro empty-substitution-p (substitution) `(null (cdr ,substitution)))ŤŤ(defmacro get-binding-pair (variable substitution)Ť "Given a VARIABLE, return its variable-value pair, if any, inŤ SUBSTITUTION."Ť `(assoc ,variable ,substitution :test #'eq))ŤŤ(defmacro add-binding-pair (variable value substitution)Ť "Make the binding of VARIABLE be VALUE in SUBSTITUTION. SUBSTITUTION isŤ constructively altered and returned."Ť `(acons ,variable ,value ,substitution))ŤŤ(defun get-ultimate-value (variable substitution)Ť "Given a VARIABLE, return either its ultimate binding, if any, inŤ SUBSTITUTION or the VARIABLE itself. (If variable X's immediate bindingŤ is variable Y and Y also has a binding, then X's ultimate binding isŤ whatever Y's ultimate binding is. We do not handle circularities.)"Ť (do (p) (nil)Ť (setf p (or (get-binding-pair variable substitution) (return variable))Ť‰ variable (binding-value p))))ŤŚŤ(defmacro do-substitutionŤ‰ ((pair substitution &optional resultform) &body body)Ť "Iterate BODY with PAIR bound to successive variable-value pairs inŤ SUBSTITUTION. RETURN and GO can be used inside the BODY. If there isŤ no early return, RESULTFORM is finally evaluated and its valueŤ returned."Ť `(dolist (,pair ,substitution ,resultform) (when ,pair ,@body)))ŤŤ(defmacro copy-substitution (substitution)Ť "Return a copy of SUBSTITUTION."Ť `(copy-alist ,substitution))ŤŚŤ#|Ť;;; This code could be used for applications where a substitution need notŤ;;; be a stack and may be destructively altered.ŤŤ(defun make-substitution (&key (test #'eq))Ť "Make an empty substitution with given retrieval predicate."Ť (vector 'substitution test (make-hash-table :test test)))ŤŤ(defmacro substitution-predicate (substitution) `(aref ,substitution 1))Ť(defmacro substitution-set (substitution) `(aref ,substitution 2))ŤŤ(defmacro substitution-count (substitution)Ť `(hash-table-count (substitution-set ,substitution)))ŤŤ(defmacro empty-substitution-p (substitution)Ť `(zerop (substitution-count ,substitution)))ŤŤ(defmacro get-binding-pair (variable substitution)Ť "Given VARIABLE, return its variable-value pair, if any, inŤ SUBSTITUTION."Ť `(gethash ,variable (substitution-set ,substitution)))ŤŤ(defun set-binding-pair (variable value substitution)Ť "Make the binding of VARIABLE be VALUE in SUBSTITUTION. SUBSTITUTION isŤ destructively altered and returned."Ť (setf (get-binding-pair variable substitution)Ť‰(make-binding-pair variable value))Ť substitution)ŤŤ(defmacro do-substitutionŤ‰ ((pair substitution &optional resultform) &body body)Ť "Iterate BODY with PAIR bound to successive variable-value pairs inŤ SUBSTITUTION. RETURN can be used inside the BODY. If there is no earlyŤ return, RESULTFORM is finally evaluated and its value returned."Ť (let ((var (make-symbol "variable")))Ť `(block nilŤ (maphash #'(lambda (,var ,pair) (declare (ignore ,var)) ,@body)Ť‰‰(substitution-set ,substitution))Ť ,resultform)))ŤŤ(defun copy-substitution (substitution)Ť "Return a copy of SUBSTITUTION."Ť (let ((s (make-substitution :test (substitution-predicate substitution))))Ť (do-substitution (pair substitution s)Ť (set-binding-pair (binding-variable pair) (binding-value pair) s))))Ť|#ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 3 :LENGTH-IN-BYTES 2344 :AUTHOR "WILDE" :CREATION-DATE 2716906682 :QFASLP NIL :LENGTH 2344 :CHARACTERS T :DIRECTORY "LISP2-CIRCULATION" :NAME "WINDOW-BRINGUP-PROCESS" :TYPE "LISP" :VERSION 4) ;;; -*- Mode:LISP; Package:USER; Fonts:(CPTFONT); Base:10 -*-ŤŤ;; Copyright (C) 1985 LISP Machine, Incorporated.ŤŤ; Title: ProcessesŤ; Subtitle: Window to bring up a process.Ť; File name: window-bringup-process.lisp and .qfaslŤŤŤ; To demo, execute (make-simple-process-window)ŤŤ; Write a window to bring up a process.ŤŤ; First, define a simple window.Ť; We need to include tv:process-mixin as a component flavor.ŤŤŤ(defflavor simple-proc-windowŤ‰ ()Ť‰ (tv:process-mixin tv:window)Ť :gettable-instance-variablesŤ :settable-instance-variablesŤ :initable-instance-variablesŤ (:default-init-plistŤ :borders 2Ť :label '(:top :centered :string "Simple Process Window")Ť :more-p nilŤ :edges-from :mouse))ŤŤŤŤŤ; Then, write a function to make a window which has a processŤ; associated with it.ŤŤ; The init option :process, below, specifies the process forŤ; the window. The argument can be a process, or it can beŤ; a list, which is used as a description for creating a process.ŤŤ; The list looks likeŤ; (initial-function make-process-options)ŤŤ; When the process starts up, it will call initial-functionŤ; with the window as its sole argument. Usually the initialŤ; function should bind terminal-io to the argument.ŤŤ(defun make-simple-process-window (&aux simple-proc-window)Ť (setq simple-proc-windowŤ‰(make-instance 'simple-proc-windowŤ‰‰ :process '(line-hack)))Ť (send simple-proc-window :activate)Ť (send simple-proc-window :expose)Ť (tv:await-window-exposure))ŤŤŤŤ; The initial function for this process is a line hack.Ť; It stops when something is typed on the keyboard.Ť; To get out of the window, just select another one.ŤŤ(defun line-hack (stream &rest ignore)Ť (let ((terminal-io stream))Ť (send stream :select)Ť (multiple-value-bind (xlim ylim)Ť‰(send stream :inside-size)Ť (loop until (send stream :tyi-no-hang) doŤ‰ (loopŤ‰ with hx = (// xlim 2)Ť‰ with hy = (// ylim 2)Ť‰ with alu = tv:alu-xorŤ‰ for cntr from 1 to (min hx hy)Ť‰ doŤ‰ (send streamŤ‰‰ :draw-lineŤ‰‰ 0 (- hy cntr) (+ hx cntr) 0 alu)Ť‰ (send streamŤ‰‰ :draw-lineŤ‰‰ (+ hx cntr) 0 xlim (+ hy cntr) alu)Ť‰ (send streamŤ‰‰ :draw-lineŤ‰‰ xlim (+ hy cntr) (- hx cntr) ylimŤ‰‰ alu)Ť‰ (send streamŤ‰‰ :draw-lineŤ‰‰ (- hx cntr) ylim 0 (- hy cntr) alu)Ť‰ )))))ŤLMFL(:BYTE-SIZE 8 :LENGTH-IN-BLOCKS 3 :LENGTH-IN-BYTES 2923 :AUTHOR "MDS" :CREATION-DATE 2734026984 :CHARACTERS T :DIRECTORY "OEHLMANNQ" :NAME "DRIB" :TYPE "LISP" :VERSION 1) Ť;Reading at top level in Lisp Listener 1.Ť;Reading in base 10 in package USER with standard Zetalisp readtable.ŤŤ(define-flavor space-ship (x-thrust y-thrust z-thrust (mass 35)) 'space-object)ŤSPACE-SHIPŤ(describe-flavor 'space-ship)ŤFlavor SPACE-SHIP directly depends on flavors: QUOTE, SPACE-OBJECTŤNot counting inherited methods, the methods for SPACE-SHIP are:Ť :SET-Z-THRUSTŤ :SET-Y-THRUSTŤ :SET-X-THRUSTŤ :Z-THRUSTŤ :Y-THRUSTŤ :X-THRUSTŤ :SET-MASSŤ :SET-ZTHRUSTŤ :MASSŤ :ZTHRUSTŤ :SET-YTHRUSTŤ :CASE :SET :Z-THRUST, :CASE :SET :Y-THRUST, :CASE :SET :X-THRUST, :CASE :SET :MASS, :CASE :SET :ZTHRUST, :CASE :SET :YTHRUST, :CASE :SET :XTHRUSTŤ :SET-XTHRUSTŤ :YTHRUSTŤ :XTHRUSTŤAutomatically-generated methods to get instance variables: X-THRUST, Y-THRUST, Z-THRUST, MASSŤAutomatically-generated methods to set instance variables: X-THRUST, Y-THRUST, Z-THRUST, MASSŤInstance variables that may be set by initialization: X-THRUST, Y-THRUST, Z-THRUST, MASSŤDefined in package USERŤProperties:Ť :SETTABLE-INSTANCE-VARIABLES:‰(X-THRUST Y-THRUST Z-THRUST MASS)Ť :GETTABLE-INSTANCE-VARIABLES:‰(X-THRUST Y-THRUST Z-THRUST MASS)Ť SI::INSTANCE-AREA-FUNCTION:‰NILŤ SI::REQUIRED-INIT-KEYWORDS:‰NILŤ SI::REMAINING-INIT-KEYWORDS:‰NILŤ SI::REMAINING-DEFAULT-PLIST:‰NILŤ SI::ALL-INITTABLE-INSTANCE-VARIABLES:‰NILŤ SI::ALL-SPECIAL-INSTANCE-VARIABLES:‰NILŤ SI::INSTANCE-VARIABLE-INITIALIZATIONS:‰NILŤ SI::MAPPED-COMPONENT-FLAVORS:‰NILŤ SI::UNMAPPED-INSTANCE-VARIABLES:‰NILŤ COMPILE-FLAVOR-METHODS:‰NILŤ SI::ALL-INSTANCE-VARIABLES-SPECIAL:‰NILŤ SI::ADDITIONAL-INSTANCE-VARIABLES:‰NILŤFlavor SPACE-SHIP does not yet have a method hash tableŤŤNILŤ(macroexpand 'space-ship)ŤSPACE-SHIPŤ(macroexpand '(define-flavor space-ship (x-thrust y-thrust z-thrust (mass 35)) 'space-object))Ť(PROGN (EVAL-WHEN (LOAD EVAL) (SI::DEFFLAVOR2 (QUOTE SPACE-SHIP) (QUOTE (X-THRUST Y-THRUST Z-THRUST (MASS 35))) (QUOTE (QUOTE SPACE-OBJECT)) (QUOTE (:INITTABLE-INSTANCE-VARIABLES :GETTABLE-INSTANCE-VARIABLES :SETTABLE-INSTANCE-VARIABLES)))) (EVAL-WHEN (COMPILE) (IF (SI::JUST-COMPILING) (LET ((SI::*JUST-COMPILING* T)) (SI::DEFFLAVOR2 (QUOTE SPACE-SHIP) (QUOTE (X-THRUST Y-THRUST Z-THRUST (MASS 35))) (QUOTE (QUOTE SPACE-OBJECT)) (QUOTE (:INITTABLE-INSTANCE-VARIABLES :GETTABLE-INSTANCE-VARIABLES :SETTABLE-INSTANCE-VARIABLES))) (SI::COMPOSE-AUTOMATIC-METHODS (SI:COMPILATION-FLAVOR (QUOTE SPACE-SHIP)))) (SI::COMPOSE-AUTOMATIC-METHODS (GET (QUOTE SPACE-SHIP) (QUOTE SI:FLAVOR))))) (EVAL-WHEN (EVAL) (SI::COMPOSE-AUTOMATIC-METHODS (GET (QUOTE SPACE-SHIP) (QUOTE SI:FLAVOR)))) (EVAL-WHEN (COMPILE LOAD EVAL)) (QUOTE SPACE-SHIP))ŤŤ(defmacro define-flavor (flavor-name vars flavors &body options)Ť `(defflavor ,flavor-name ,vars ,flavorsŤ :inittable-instance-variablesŤ :gettable-instance-variablesŤ :settable-instance-variablesŤ ,@options))ŤDEFINE-FLAVORŤ(dribble)