throbber
GARNET SOURCE CODE EXCERPTS
`
`src/kr/kr.lisp
`
`src/opal/aggregates.lisp
`
`src/opal/basics.lisp
`
`src/opal/new-defs.lisp
`
`src/opal/update.lisp
`
`src/opal/update-window.lisp
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`APPLE 1006.0001
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`;;; -*- Mode: LISP; Syntax: Common-Lisp; Package: KR; Base: 10 -*-
`
`
`;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
`;;; The Garnet User Interface Development Environment
`;;; Copyright (c) 1989, 1990 Carnegie Mellon University
`;;; All rights reserved. The CMU software License Agreement specifies
`;;; the terms and conditions for use and redistribution.
`;;;
`;;; If you want to use this code or anything developed as part of the
`;;; Garnet project, please contact Brad Myers (Brad.Myers@CS.CMU.EDU).
`;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
`
`
`
`
`;;; TO DO:
`;;; - G-CACHED-VALUE: multiple values!
`;;; - DESTROY-CONSTRAINT: code to set the value after formula is
`destroyed
`;;; (for multiple-value case)
`;;; - fix up APPEND-VALUE to be more efficient.
`;;; - DESTROY-SLOT and DELETE-VALUE-N : do the appropriate thing when the
`;;; slot/value being destroyed is being depended upon by others. In
`;;; particular:
`;;; - destroy-slot does NOT work for multi-formula slots;
`;;; - delete-value-n does not work at all for formula values.
`;;; - SET-VALUES must deal with demons properly!
`;;; - SET-VALUES must deal with formulas properly!
`;;; - Replace DELETE-FORMULA by DE-INSTALL-FORMULA ??
`;;; - check out the "Are we installing a formula ...?" part in s-value-n;
`is
`;;; it ever used?
`;;; - fix COPY-DOWN-FORMULAS to deal with multiple values!
`;;; - dependencies should be on a schema/slot/value basis, instead of
`simply
`;;; schema/slot. Use a 3-slot structure, which is cheaper than both an
`;;; array and a list of 3 elements.
`;;; - PROPAGATE-CHANGE: FIX FOR MULTIPLE VALUES !!!!!
`;;; - delete-value-n (check inheritance)
`;;; - set relation slots, have inheritance propagated
`;;; - check all places where formulas are assumed to be in first position
`only.
`;;; - DESTROY-SCHEMA: change last part, which says ";; Destroy formulas
`that
`;;; used to hang off slots of this schema". Check it out thoroughly.
`;;;
`
`
`;;; The KR-DEBUG package is used to intern automatically-created names
`for
`;;; unnamed schemata.
`;;;
`(in-package "KR-DEBUG")
`
`kr.lisp
`
`APPLE 1006.0002
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
` ;; the object programming interface
` DEFINE-METHOD METHOD-TRACE KR-SEND CALL-PROTOTYPE-METHOD
` CREATE-INSTANCE CREATE-PROTOTYPE
`
` *ALLOW-CHANGE-TO-CACHED-VALUE*
` WITH-DEMONS-DISABLED
` FORMULA-P
` GV GVL GV-LOCAL G-VALUE G-CACHED-VALUE
` MARK-AS-CHANGED MARK-AS-INVALID
` FORMULA O-FORMULA CHANGE-FORMULA))
`
`
`
`;;; The KR package contains the whole system and exports the functional
`;;; interface.
`;;;
`(in-package "KR")
`
`
`
`(export '(PS S NAME-FOR-SCHEMA
`
` CREATE-SCHEMA CREATE-RELATION
`
` SCHEMA-P RELATION-P IS-A-P HAS-SLOT-P
`
` GET-VALUE GET-VALUES
`
` G-LOCAL-VALUE GET-LOCAL-VALUES GET-LOCAL-VALUE
`
` DOVALUES DOSLOTS DO-PRINTABLE-SLOTS S-VALUE S-VALUE-N
`
` SET-VALUES APPEND-VALUE DELETE-VALUE-N
`
` DESTROY-SLOT DESTROY-SCHEMA DESTROY-CONSTRAINT
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`(defparameter *kr-version* "1.1.27")
`
`
`;;; -------------------------------------------------- Internal
`structures.
`
`
`
`
`;;; The internal representation of a schema is as a structure, where the
`;;; <name> slot holds the name (or internal number) of the schema and the
`;;; <slots> slot holds a p-list of slot names and slot values.
`;;;
`(defstruct (schema (:print-function print-the-schema))
` name ; the schema name, or a number
` slots ; area for overflow slots (a plist)
` is-a ; this and the following are special slots in all schemata
` update-slots
` )
`
`
`;;; The basis KR schema (most schemata are of this type).
`;;;
`
`kr.lisp
`
`APPLE 1006.0003
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`(defstruct (a-schema (:include schema) (:print-function print-the-
`schema))
` left
` top
` width
` height
` )
`
`
`;;; This structure is similar to a schema, but is used to store formulas.
`;;; It prints out with an F instead of an S, and it uses the same
`positions for
`;;; different functions.
`;;;
`(defstruct (a-formula (:include schema) (:print-function print-the-
`schema))
`; the expression which gets evaluated to yield the value
` kr-function
` kr-depends-on ; list of schemata on which this function depends
` kr-form
`; symbolic form of the "function" (for compiled
`formulas)
` kr-schema ; schema on which this formula is installed
` kr-slot
`; slot on which this formula is installed
` cached-value
`; the cached value
` cached-number ; valid/invalid bit, and sweep mark
` kr-path ; holds cached paths
` )
`
`
`
`;;; We do not necessarily use the built-in structure predicate, because
`it
`;;; seems to be terribly slow on Lisp machines.
`;;;
`
`(defmacro formula-p (thing)
` `(a-formula-p ,thing))
`
`
`
`
`;;; -------------------------------------------------- Low-level slot
`access
`
`
`
`(defvar *schema-counter* 0
` "This variable is simply used to generate schema numbers for schemata
`that
` are created with (create-schema NIL).")
`
`
`
`(eval-when (eval compile load)
` (defparameter *schema-slots*
`
`kr.lisp
`
`APPLE 1006.0004
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
` '((:is-a . schema-is-a)
` (:update-slots . schema-update-slots)
` (:left . a-schema-left)
` (:top . a-schema-top)
` (:width . a-schema-width)
` (:height . a-schema-height))
` "Names and slot accessorss in a schema structure"))
`
`;;; Removed :is-a and :update-slots from *formula-slots* -- ECP 4/3/90
`(eval-when (eval compile load)
` (defparameter *formula-slots*
` '((:kr-function . a-formula-kr-function)
` (:kr-depends-on . a-formula-kr-depends-on)
` (:kr-form . a-formula-kr-form)
` (:kr-schema . a-formula-kr-schema)
` (:kr-slot . a-formula-kr-slot)
` (:cached-value . a-formula-cached-value)
` (:cached-number . a-formula-cached-number))))
`
`(eval-when (eval compile load)
` (defparameter *formula-safe-slots*
` '((:is-a . schema-is-a)
` (:update-slots . schema-update-slots)
` (:kr-function . a-formula-kr-function)
` (:kr-form . a-formula-kr-form))))
`
`
`
`(eval-when (eval compile load)
` ;; Associate the slot reference number to the slot names for special
`slots
` ;; (which are simply keywords, of course).
` (dolist (l *schema-slots*)
` (setf (get (car l) :KR-SLOT-NUMBER) (cdr l)))
` (dolist (l *formula-slots*)
` (setf (get (car l) :KR-SLOT-NUMBER) (cdr l))))
`
`
`
`;;; --------------------------------------------------
`
`
`(defvar *warning-on-create-schema* T
` "If nil, no warning is printed when create-schema is redefining an
`existing
` schema.")
`
`(defvar *warning-on-circularity* nil
` "Set this to NIL to prevent warning when a circularity is detected.")
`
`(defvar *warning-on-evaluation* nil
` "If non-NIL, a warning is printed every time a formula is re-evaluated.
` This may be useful during debugging.")
`
`
`kr.lisp
`
`APPLE 1006.0005
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`
`(eval-when (compile load eval)
` (defvar *print-new-instances* T))
`
`
`(defvar *warning-on-null-link* NIL
` "If non-NIL, a warning is printed when a null link is evaluated inside
`a
` GV (or GVL) within a formula. This is the case when the stale value of
`the
` formula is reused.")
`
`(defvar *warning-on-disconnected-formula* T
` "If nil, no warning is printed when propagate-change sees a
`disconnected
` formula.")
`
`
`(defvar *count-formulas* T
` "If nil, we are setting a relation slot with objects which are
`formulas,
` but should NOT be considered as such (for instance, this happens in
` inherited formulas). The relation should then be followed as is,
`rather
` than getting the value of each formula!")
`
`
`
`(defvar *use-formulas-for-inheritance* t
` "If this is NIL, formulas on relation links are NOT expanded when
`performing
` inheritance. This is needed when inside inherited formulas, which are
`all
` of the form (:IS-A another-formula)")
`
`
`(defvar *within-g-value* nil
` "Set to non-nil within a sub-formula evaluation")
`
`
`(defvar *sweep-mark* 0
` "Used as a sweep mark to detect circularities")
`
`
`(defvar *demons-disabled* nil
` "May be bound to T to cause demons NOT to be executed when a slot is
`set.")
`
`
`(defvar *allow-change-to-cached-value* T
` "If non-nil, changes to a constrained slot (i.e., a slot which contains
`a
` formula) will be reflected immediately in the formula's cached value,
`without
`
`kr.lisp
`
`APPLE 1006.0006
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
` of course modifying the formula.")
`
`
`(defvar *pre-set-demon* nil
` "May be bound to a function to be called as a slot is set in a schema
` with the slots new-value.")
`
`(defvar *invalidate-demon* 'invalidate-demon
` "The demon that gets called when a slot on the :update-slots of a
`schema
` is changed.")
`
`
`(defvar *schema-self* nil
` "The schema being acted upon by the accessor functions.")
`
`(defvar *schema-slot* nil
` "The slot in *schema-self* being acted upon by the accessor
`functions.")
`
`(defvar *current-formula* nil
` "The formula being acted upon by the accessor functions.")
`
`(defvar *last-formula* nil
` "Similar to *current-formula*, used for debugging only.")
`
`
`
`(defvar *inheritance-relations* '()
` "All relations in this list perform inheritance.")
`
`(defvar *inheritance-inverse-relations* '()
` "Inverses of all relations which perform inheritance.")
`
`(defvar *relations* '()
` "An a-list of relations known to the system, with their inverse(s).
` Used for the creation of automatic reverse-links.")
`
`
`(defvar *schema-is-new* nil
` "If non-nil, we are inside the creation of a new schema. This
`guarantees
` that we do not have to search for inverse links when creating
`relations,
` and avoids the need to scan long is-a-inv lists.")
`
`
`(defvar *print-as-structure* T
` "If non-nil, schema names are printed as structure references.")
`
`(defvar *print-structure-slots* nil
` "List of slots that should be printed when printed schemata as
`structures.")
`
`
`kr.lisp
`
`APPLE 1006.0007
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`
`
`
`;;; --------------------------------------------------
`
`
`(defmacro slot-accessor (schema sl)
` (if (keywordp sl)
` ;; Slot name is known at compile time.
` (let ((function (get sl :KR-SLOT-NUMBER)))
`
`(if function
`
` ;; Slot name is a special name
`
` `(,function ,schema)
`
` ;; Slot name is not a special name.
`
` `(getf (schema-slots ,schema) ,sl)))
` ;; Slot name is only known at runtime, so do the right thing (this
` ;; CASE is executed at runtime, unlike the first one). This is
` ;; here mostly for safety reasons, and is not used at the user
`level.
` `(let ((function (get ,sl :KR-SLOT-NUMBER)))
`
` (if function
`
` (funcall function ,schema)
`
` (getf (schema-slots ,schema) ,sl)))))
`
`
`
`
`(defun accessor-constructor-fn (x)
` `(,(car x) (setf (,(cdr x) schema) value)))
`
`
`;;; This function's definition is computed from the current contents of
`the
`;;; list of special schema slots.
`;;; The (generated) body function is essentially a big CASE statement
`which
`;;; sets the appropriate slot.
`;;;
`(eval `(defun set-any-slot (schema the-slot value)
`
` ,(append '(case the-slot)
`
`
` (mapcar #'accessor-constructor-fn *schema-slots*)
`
`
` (mapcar #'accessor-constructor-fn *formula-slots*)
`
`
` '((t (setf (getf (schema-slots schema) the-slot)
`value))))))
`
`;;; Now compile the thingie
`(compile 'set-any-slot)
`
`
`
`;;; <value> must be a complete value descriptor.
`;;;
`(defmacro set-slot-accessor (schema sl value)
` (let ((function (get sl :KR-SLOT-NUMBER)))
`
`kr.lisp
`
`APPLE 1006.0008
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
` (if function
`
``(setf (,function ,schema) ,value)
`
`(if (keywordp sl)
`
` ;; Slot name is known at compile time, but not a special name.
`
` `(setf (getf (schema-slots ,schema) ,sl) ,value)
`
` ;; Slot name is only known at runtime, so do the right thing
`(this
`
` ;; CASE is executed at runtime, unlike the first one). This is
`
` ;; here mostly for safety reasons, and is not used at the user
`level.
`
` `(set-any-slot ,schema ,sl ,value)))))
`
`
`;;; A couple of specialized accessors for formula slots.
`;;;
`(defmacro on-schema (formula)
` `(a-formula-kr-schema ,formula))
`
`
`(defmacro on-slot (formula)
` `(a-formula-kr-slot ,formula))
`
`
`
`
`
`
`;;; Iterate the <body> for all the slots in the <schema>, with the
`variable
`;;; <slot> bound to each slot in turn.
`;;;
`(defmacro iterate-accessors ((a-schema &optional (inherited T))
`
`
`
` &body body)
` `(do* ((schema ,a-schema)
`
` (the-slot (slots-accessor schema) (cddr the-slot))
`
` (slot (car the-slot) (car the-slot)))
`
`((null the-slot)
`
` ;; Now apply to special slots as well (if they have a value, of
`course).
`
` (dolist (entry (if (a-schema-p schema)
`
`
`
` *schema-slots*
`
`
`
` *formula-safe-slots*))
`
` ,@(if inherited
`
`
` ;; simpler expression: any slot will do
`
`
` `((when (funcall (cdr entry) schema)
`
`
` (setf slot (car entry))
`
`
` ,@body))
`
`
` ;; more complex: only local slots will do
`
`
` `((let ((values (funcall (cdr entry) schema)))
`
`
` (when (and values
`
`
`
`
`(not (is-inherited values)))
`
`
` (setf slot (car entry))
`
`
` ,@body))))))
` ,@(if inherited
`
`kr.lisp
`
`APPLE 1006.0009
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`
` body
` `((let ((values (slot-accessor schema slot)))
` (when (and values
`
`
` (not (is-inherited values))
`
`
` (not (null (cdr values))))
`
` ,@body))))))
`
`
`
`
`
`
`
`
`
`
`
`
`;;; -------------------- Definitions of value-information bits.
`
`
`
`(eval-when (eval compile load)
` ;; bit is 1 if slot contains inherited values, 0 for local values
` (defparameter *inherited-bit* 0)
` ;; bit is 1 if any other schema inherited the value from here
` (defparameter *is-parent-bit* 1)
` ;; bit is 1 if any formula depends on this slot
` (defparameter *depended-bit* 2)
` ;; bit is 1 if slot contains at least one formula, 0 otherwise. It
`should
` ;; be last, since formulas can be a multi-bit field.
` (defparameter *formula-bit* 3))
`
`
`(eval-when (eval compile load)
` (defparameter *local-mask* 0)
` (defparameter *inherited-mask* (ash 1 *inherited-bit*))
` (defparameter *is-parent-mask* (ash 1 *is-parent-bit*))
` (defparameter *depended-mask* (ash 1 *depended-bit*))
` (defparameter *formula-mask* (ash 1 *formula-bit*))
` (defparameter *all-but-inherited-mask* (lognot *inherited-mask*))
` (defparameter *all-but-parent-mask* (lognot *is-parent-mask*)))
`
`(defparameter *middle-mask*
` (logior *inherited-mask* *is-parent-mask* *depended-mask*)
` "All bits but 'has formulas'")
`
`(defparameter *all-but-formula*
`
` (logior *inherited-mask* *is-parent-mask* *depended-mask*))
`
`(defparameter *no-value* (list *inherited-mask*)
` "When no value is found, use this descriptor (inherited)")
`
`(defmacro descriptor-is-inherited (thing)
` `(logbitp ,*inherited-bit* ,thing))
`
`(defmacro is-inherited (thing)
` `(logbitp ,*inherited-bit* (car ,thing)))
`
`
`kr.lisp
`
`APPLE 1006.0010
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`;;; Bind <entry> if it is a complex expression, since this macro expands
`it
`;;; twice.
`;;;
`(defmacro set-is-inherited (entry new-value)
` (if new-value
` `(setf (car ,entry) (logior (car ,entry) ,*inherited-mask*))
` `(setf (car ,entry) (logand (car ,entry) ,(lognot *inherited-
`mask*)))))
`
`
`(defmacro not-inherited (thing)
` ;; This relies on the fact the *inherited-bit* is bit 0.
` `(evenp (car ,thing)))
`
`(defmacro is-parent (thing)
` `(logbitp ,*is-parent-bit* (car ,thing)))
`
`(defmacro descriptor-is-parent (thing)
` `(logbitp ,*is-parent-bit* ,thing))
`
`(defmacro is-depended (thing)
` `(and ,thing (logbitp ,*depended-bit* (car ,thing))))
`
`(defmacro has-formulas (thing)
` `(logbitp ,*formula-bit* (car ,thing)))
`
`(defmacro set-has-formulas (thing value)
` `(if ,value
` (setf (car ,thing) (logior (car ,thing) ,*formula-mask*))
` (setf (car ,thing) (logand (car ,thing) ,(lognot *formula-
`mask*)))))
`
`
`(defmacro get-local-value (schema slot)
` `(let ((values (slot-accessor ,schema ,slot)))
` (when (and values (not (is-inherited values)))
` (cadr values))))
`
`
`(defmacro get-local-values (schema slot)
` `(let ((values (slot-accessor ,schema ,slot)))
` (and values (not-inherited values)
`
` (cdr values))))
`
`
`(defmacro slots-accessor (thing)
` `(schema-slots ,thing))
`
`(defmacro name-accessor (thing)
` `(schema-name ,thing))
`
`
`
`
`kr.lisp
`
`APPLE 1006.0011
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`
`
`;;; --------------------------------------------------
`
`;;; This macro is used by macros such as GV or G-VALUE, which can
`;;; be called with any number of slot names and expand into
`;;; a nested chain of calls to <accessor-function>.
`;;;
`(defmacro expand-accessor (accessor-function schema &rest slots)
` (if (= (length slots) 1)
` ;; Supply default position (0).
` (setf slots (list (car slots) 0)))
` (if slots
` ;; At least one slot was specified.
` (let* ((last-thing (car (last slots)))
`
` (position
`
` ;; ASSUMPTION: the last of the <slots> should be either an
`
` ;; actual slot, known at compile time, or else a position
`number.
`
` ;; In other words, the last slot CANNOT be specified by an
`
` ;; expression or a variable.
`
` (cond ((keywordp last-thing)
`
`
` 0)
`
`
` (t
`
`
` (prog1
`
`
`
` (car (last slots))
`
`
` ;; Eliminate position number from list of slots.
`
`
` (setf (cdr (nthcdr (- (length slots) 2) slots))
`
`
`
` NIL)))))
`
` (kernel schema))
`
`;; "Grow" the kernel by wrapping more gv-fn's around it
`
`(do ((slot slots (cdr slot)))
`
` ((null slot))
`
` (setf kernel `(,accessor-function ,kernel ,(car slot)
`
`
`
`
`
` ,(if (null (cdr slot)) position 0))))
`
`kernel)
` ;; No slots!
` (error "expand-accessor: at least one slot is required")))
`
`
`
`;;; ---------------------------------------------- CACHED VALUES
`(CONSTRAINTS)
`
`
`;;; The following macros are used to reference particular slots from the
`;;; cached value of formulas.
`
`(defmacro cached-value (thing)
` `(a-formula-cached-value ,thing))
`
`(defmacro cache-is-valid (thing)
` `(logbitp 0 (a-formula-cached-number ,thing)))
`
`
`kr.lisp
`
`APPLE 1006.0012
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`
`(defmacro set-cache-is-valid (thing value)
` (if value
` `(setf (a-formula-cached-number ,thing)
`
` (logior (a-formula-cached-number ,thing) 1))
` `(setf (a-formula-cached-number ,thing)
`
` (logand (a-formula-cached-number ,thing) ,(lognot 1)))))
`
`
`(defmacro cache-mark (thing)
` `(logand (a-formula-cached-number ,thing) ,(lognot 1)))
`
`(defmacro set-cache-mark (thing mark)
` `(setf (a-formula-cached-number ,thing)
`
` (logior (logand (a-formula-cached-number ,thing) 1) ,mark)))
`
`
`
`;;; --------------------------------------------------
`
`
`
`;;; Execute the <body> with pre- and post-demons disabled.
`;;;
`(defmacro with-demons-disabled (&body body)
` `(let ((*demons-disabled* t))
` ,@body))
`
`
`
`;;;; RELATION-P
`;;;
`(defmacro relation-p (slot)
` `(assoc ,slot *relations*))
`
`
`
`;;; -------------------------------------------------- MACROS
`
`
`
`;;;; DOSLOTS
`;;;
`;;; Executes the <body> with <slot> bound in turn to each slot in the
`<schema>.
`;;;
`(defmacro doslots ((slot-var a-schema) &body body)
` `(iterate-accessors (,a-schema NIL)
` (let ((,slot-var slot))
` ,@body)))
`
`
`
`;;;
`
`kr.lisp
`
`APPLE 1006.0013
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`;;;
`(defmacro get-value (schema slot)
` `(let ((value (or (slot-accessor ,schema ,slot)
`
`
` (g-value-inherit-values ,schema ,slot))))
` (cadr value)))
`
`
`;;;
`(defmacro g-value-fn (*schema-self* slot the-position)
` `(let* ((*schema-self* ,*schema-self*)
`
` (values (or (slot-accessor *schema-self* ,slot)
`
`
` (g-value-inherit-values *schema-self* ,slot)))
`
` (value ,(cond ((not (numberp the-position))
`
`
`
` `(if (zerop ,the-position)
`
`
`
` (cadr values)
`
`
`
` (nth (1+ ,the-position) values)))
`
`
`
`((zerop the-position)
`
`
`
` `(cadr values))
`
`
`
`(t
`
`
`
` `(nth ,(1+ the-position) values)))))
` (if (formula-p value)
`
` (g-value-formula-value *schema-self* ,slot value)
`
` ;; We are working with an ordinary value.
`
` value)))
`
`;;;
`(defmacro g-local-value-fn (*schema-self* slot position)
` `(let ((values (slot-accessor ,*schema-self* ,slot)))
` (when (and values
`
`
`(not (is-inherited values)))
` (let ((value (nth ,(if (numberp position)
`
`
`
` (1+ position)
`
`
`
` `(1+ ,position)) values)))
`
` (if (formula-p value)
`
` (g-value-formula-value ,*schema-self* ,slot value)
`
` ;; We are working with an ordinary value.
`
` value)))))
`
`
`
`;;;; G-VALUE
`;;; This macro expands into nested calls to g-value-fn. For example:
`;;; (g-value schema :slot1 :slot2 :slot3 5) expands into
`;;; (g-value-fn (g-value-fn (g-value-fn schema :slot1 0) :slot2 0) :slot3
`5)
`;;;
`(defmacro g-value (schema &rest slots)
` (if slots
` `(expand-accessor g-value-fn ,schema ,@slots)
` `(progn ,schema)))
`
`
`
`;;;; G-LOCAL-VALUE
`
`kr.lisp
`
`APPLE 1006.0014
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`;;;
`(defmacro g-local-value (schema &rest slots)
` (if slots
` `(expand-accessor g-local-value-fn ,schema ,@slots)
` `(progn ,schema)))
`
`
`
`;;;; S-VALUE
`;;; The basic value-setting function.
`;;; NOTE:
`;;; if *allow-change-to-cached-value* is nil (the default), a slot which
`;;; contains a formula cannot be overwritten with a value, but just with
`;;; another formula.
`;;;
`(defmacro s-value (schema slot value)
` `(s-value-n ,schema ,slot 0 ,value))
`
`
`
`
`;;;; GET-VALUES
`;;;
`(defmacro get-values (schema slot)
` `(let ((values (or (slot-accessor ,schema ,slot)
`
`
` (g-value-inherit-values ,schema ,slot))))
` (when values
` (cdr values))))
`
`
`
`;;;; DOVALUES
`;;; Executes <body> with <var> bound to all the values of <slot> in
`<schema>.
`;;; Note that the values are as per get-values.
`;;;
`(defmacro dovalues ((variable schema slot &key (local nil) (result nil)
`
`
`
` (formulas T) (in-formula NIL))
`
`
` &rest body)
` `(let* ((schema ,@(if (eq schema :SELF)
`
`
`
``(*schema-self*)
`
`
`
``(,schema)))
`
` (values ,(if local
`
`
` `(slot-accessor schema ,slot)
`
`
` `(or (slot-accessor schema ,slot)
`
`
`
` (inherit-slot-accessor schema ,slot)))))
` ;; If :IN-FORMULA is non-nil, do extra work to set up the
`dependencies.
` ,@(if in-formula
`
` `((pushnew schema (slot-accessor *current-formula* :KR-DEPENDS-
`ON))))
` ,@(if in-formula
`
` `((let ((entry (assoc ,slot
`
`
`
`
` (get-local-values schema :DEPENDED-SLOTS))))
`
`kr.lisp
`
`APPLE 1006.0015
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
` (unless entry
`
`
` ;; This slot was not yet depended on by anybody.
`
`
` (push (setf entry (list ,slot))
`
`
` (get-local-values schema :DEPENDED-SLOTS))
`
`
` (let ((the-entry (slot-accessor schema ,slot)))
`
`
` (unless the-entry
`
`
` (format t "DOVALUES: Entry is nil~%"))
`
`
` ;; Mark this value as being depended on by someone.
`
`
` (setf (car the-entry)
`
`
`
` (logior (car the-entry) *depended-mask*))))
`
` (pushnew *current-formula* (cdr entry)))))
`
` ;; Now iterate
` (cond ((null values)
`
` nil)
`
` ,@(cond ((eq local T)
`
`
` `(((is-inherited values)
`
`
` NIL)))
`
`
` ((null local)
`
`
` NIL)
`
`
` (t
`
`
` `(((and ,local
`
`
`
` (is-inherited values))
`
`
` NIL))))
`
` #+COMMENT
`
` ,@(if local
`
`
` `(((is-inherited values)
`
`
` NIL)))
`
` (t
`
` ,@(when formulas
`
`
`;; Extra code for the case FORMULAS = T
`
`
``((let ((has-f (has-formulas values)))
`
`
` (dolist (,variable (cdr values))
`
`
` ;; Generate test for formula-p, unless :FORMULAS is nil
`
`
` (if (and has-f (formula-p ,variable))
`
`
`
` (setf ,variable
`
`
`
`
`(g-value-formula-value schema ,slot ,variable)))
`
`
` ,@body))))
`
` ,@(unless formulas
`
`
`;; Less code for the case FORMULAS = NIL
`
`
``((dolist (,variable (cdr values))
`
`
` ,@body)))))
` ,result))
`
`
`
`
`;;; Looks in the :UPDATE-SLOTS of the <schema> to determine whether the
`<slot>
`;;; has an associated demon. This gives us the freedom to let different
`;;; schemata have demons on possibly different slots.
`;;;
`(defmacro slot-requires-demon (schema slot)
` `(member ,slot (get-value ,schema, :UPDATE-SLOTS)))
`
`
`kr.lisp
`
`APPLE 1006.0016
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`
`
`
`
`;;; ---------------------------------------- Setf forms for several
`macros
`
`(defsetf slot-accessor set-slot-accessor)
`
`(defsetf g-value s-value)
`
`(defsetf get-values set-values)
`
`(defsetf get-local-values set-values)
`
`
`
`
`;;; -------------------------------------------------- INTERNALS
`
`
`;;; This is for internal use only.
`(defun get-value-function (schema slot)
` (let* ((value (or (slot-accessor schema slot)
`
`
` (g-value-inherit-values schema slot))))
` (cadr value)))
`
`
`
`
`(defun get-values-function (schema slot)
` (cdr (or (slot-accessor schema slot)
`
` (g-value-inherit-values schema slot))))
`
`
`
`
`;;; Internal function. Like GET-VALUE, but takes a position parameter.
`;;;
`(defun get-value-n (schema slot position)
` (elt (or (slot-accessor schema slot)
`
` (g-value-inherit-values schema slot)) (1+ position)))
`
`
`
`;;; -------------------------------------------------- PRINTING AND
`DEBUGGING
`
`
`(defparameter *debug-names-length* 500)
`
`(defvar *debug-names* (make-array *debug-names-length*))
`(defvar *debug-index* -1)
`
`
`kr.lisp
`
`APPLE 1006.0017
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`54
`
`
`(defvar *intern-unnamed-schemata* T
` "This variable may be set to NIL to prevent PS from automatically
`creating
` any unnamed schemata it prints out.")
`
`
`
`;;; This version does not cause any creation of symbol. It simply
`records
`;;; the schema in an array, thus creating a semi-permanent way to refer
`;;; to a schema.
`;;;
`(defun cache-schema-name (schema name)
` (unless (find-if #'(lambda (x)
`
`
` (and x (eql (name-accessor x) name)))
`
`
` *debug-names*)
` ;; A new schema. Store it in the next position (cycle if
` ;; we reach the end of the array).
` (setf (aref *debug-names*
`
`
`(setf *debug-index*
`
`
` (mod (incf *debug-index*) *debug-names-length*)))
`
` schema)))
`
`
`
`;;; This version creates symbols for all automatic schema names that
`happen to
`;;; be printed out.
`;;;
`(defun make-new-schema-name (schema name)
` (let* ((debug-package (find-package "KR-DEBUG"))
`
` parent
`
` (symbol (intern (cond ((stringp name)
`
`
`
`
`;; a name-prefix schema
`
`
`
`
`(format nil "~A-~D"
`
`
`
`
`
`name (incf *schema-counter*)))
`
`
`
` ((setf parent (get-value schema :is-a))
`
`
`
`
`(let ((parent-name (schema-name parent)))
`
`
`
`
` (when (or (integerp parent-name)
`
`
`
`
`
` (stringp parent-name))
`
`
`
`
` ;; Parent is unnamed yet - force a name.
`
`
`
`
` (with-output-to-string (bit-bucket)
`
`
`
`
` (print-the-schema parent bit-bucket 0))
`
`
`
`
` (setf parent-name (schema-name parent)))
`
`
`
`
` (format nil "~A-~D" parent-name name)))
`
`
`
` (t
`
`
`
`
`(format nil "~C~D"
`
`
`
`
`
`(if (formula-p schema) #\F #\S)
`
`
`
`
`
`name)))
`
`
`
` debug-package)))
` (set symbol schema)
` (setf (schema-name schema) symbol)
` (export symbol debug-package)))
`
`kr.lisp
`
`APPLE 1006.0018
`
`

`

`1
`2
`3
`4
`5
`6
`7
`8
`9
`10
`11
`12
`13
`14
`15
`16
`17
`18
`19
`20
`21
`22
`23
`24
`25
`26
`27
`28
`29
`30
`31
`32
`33
`34
`35
`36
`37
`38
`39
`40
`41
`42
`43
`44
`45
`46
`47
`48
`49
`50
`51
`52
`53
`
`
`
`
`(defun print-the-schema (schema stream level)
` (declare (ignore level))
` (let ((name (schema-name schema)))
` ;; This version is for debugging. Record the latest schemata in the
` ;; array.
` (cond ((or (integerp name) (stringp name))
`
` ;; This is a nameless schema. Print it out, and record it in
`the
` ;; debugging array.
`
` (if *intern-unnamed-schemata*
`
` (make-new-schema-name schema name))
`
` (cache-schema-name schema name)
`
` ;; This gives control over whether unnamed schemata are
`
`interned.
`
` (setf name (schema-name schema)))
`
` ((null name)
`
` ;; This was a deleted schema
`
` (setf name '*DESTROYED*)))
` (if *print-as-structure*
`
`(progn
`
` (format stream "#k<~S" name)
`
` (dolist (slot *print-structure-slots*)
`
` (let ((value (g-value schema slot)))
`
` (when value
`
`
`(format stream " (~S ~S)" slot value))))
`
` (format stream ">"))
`
`(format stream "~S" name))))
`
`
`
`;;;; NAME-FOR-SCHEMA
`;;; Given a schema, returns its string name.
`;;; Note that this returns the pure name, without the #k<> notation.
`;;;
`(defun name-for-schema (schema)
` "Given a schema, returns its printable name as a string. The string
` CANNOT be destructively modified."
` (let ((name (schema-name schema)))
` (when (or (integerp name) (stringp name))
` ;; This is a nameless schema. Print it out, and record it in the
` ;; debugging array.
` (if *intern-unnamed-schemata*
`
` (make-new-schema-name schema name))
` (cache-schema-name schema name)
` ;; This gives control over whether unnamed s

This document is available on Docket Alarm but you must sign up to view it.


Or .

Accessing this document will incur an additional charge of $.

After purchase, you can access this document again without charge.

Accept $ Charge
throbber

Still Working On It

This document is taking longer than usual to download. This can happen if we need to contact the court directly to obtain the document and their servers are running slowly.

Give it another minute or two to complete, and then try the refresh button.

throbber

A few More Minutes ... Still Working

It can take up to 5 minutes for us to download a document if the court servers are running slowly.

Thank you for your continued patience.

This document could not be displayed.

We could not find this document within its docket. Please go back to the docket page and check the link. If that does not work, go back to the docket and refresh it to pull the newest information.

Your account does not support viewing this document.

You need a Paid Account to view this document. Click here to change your account type.

Your account does not support viewing this document.

Set your membership status to view this document.

With a Docket Alarm membership, you'll get a whole lot more, including:

  • Up-to-date information for this case.
  • Email alerts whenever there is an update.
  • Full text search for other cases.
  • Get email alerts whenever a new case matches your search.

Become a Member

One Moment Please

The filing “” is large (MB) and is being downloaded.

Please refresh this page in a few minutes to see if the filing has been downloaded. The filing will also be emailed to you when the download completes.

Your document is on its way!

If you do not receive the document in five minutes, contact support at support@docketalarm.com.

Sealed Document

We are unable to display this document, it may be under a court ordered seal.

If you have proper credentials to access the file, you may proceed directly to the court's system using your government issued username and password.


Access Government Site

We are redirecting you
to a mobile optimized page.





Document Unreadable or Corrupt

Refresh this Document
Go to the Docket

We are unable to display this document.

Refresh this Document
Go to the Docket