Made SCHEMA-P faster. Modified g-value-body so that even if GARNET-DEBUG is on, g-value and friends run a lot faster. This adds back most of the improvements for the case where GARNET-DEBUG is off. [10-29-1993 David Kosbie, Dario Giuse] Added David Kosbie's fix to APPLY-PROTOTYPE-METHOD, which had failed to be updated when call-prototype-method was fixed. [10-26-1993 Dario Giuse] Modified the conditional definition of REALP, as per the following message: The small change is to just add ALLEGRO-V3.1 to the switch before the code in kr.lisp: #+(or LUCID ALLEGRO-V3.1) ;;; REALP seems to be undefined on these lisps. ;;; (let ((realp-symbol (find-symbol "REALP" 'lisp))) [10-19-1993 Dario Giuse] Added Pedro's fix to DESTROY-SLOT to make sure the schema was properly deleted. [10-11-1993 Dario Giuse] Fixed a bug in ADD-NEW-TYPE which caused declarations such as (def-kr-type ACCELERATORS-TYPE () 'list "[list of lists: ((#\r \"Alt-r\" #\meta-r)...)]") which used a type body (i.e., 'list) already defined to actually lose the type definition. Exported kr:get-type-definition [10-8-1993 Dario Giuse] Added a new &key argument to PS, :stream. This argument (default value *standard-output*) allows a stream to be specified, thus redirecting all of PS's output to a stream other than the terminal. [9-22-1993 Dario Giuse] Added a SETF form for GV, which works as follows: - at the top level, (setf (gv object slots) value) is identical to (s-value object slots value); - if embedded in a formula, it is identical to the above, except that it also sets up a dependency, just like GV would. Added a new, non-exported function, kr::get-type-definition. Given the symbol which names a KR type (e.g., 'KR-BOOLEAN), this function returns the type expression that was used to define the type. Syntax: (kr::get-type-definition type-symbol) Example: (get-type-definition 'bitmap-or-nil) ==> (OR NULL (IS-A-P OPAL:BITMAP)) [9-21-1993 Dario Giuse] Eliminated code which caused a value change in a formula in a prototype to physically delete all formulas which were inherited from that formula. This caused such an operation to delete and recreate formulas in the instances. This bug was reported by Andy Mickish. [9-14-1993 Dario Giuse] Eliminated BREAK in GV; replaced with CERROR. The error message is now cleaner and indicates whether the GV occurred inside a formula or at the top level. Eliminated BREAK in CREATE-INSTANCE for the case when NIL is used instead of a slot specifier. Also, gave better error message. Fixed "illegal instruction" error caused by a slot specification in CREATE-INSTANCE which was a symbol instead of a correct specifier. This situation now gives a meaningful error message. [9-13-1993 Dario Giuse] Exported the functions GET-DECLARATIONS and GET-SLOT-DECLARATIONS from the KR package. [8-19-1993 Dario Giuse] Added the non-exported function kr::SELF-OLD-VALUE, which can be used within formulas to access the currently cached value of the formula. This allows formulas to do destructive modifications in the case where their value is a list, an array, or some other structured object. The syntax is: (kr::self-old-value) If there is no currently cached value, the function returns NIL. [8-9-1993 Dario Giuse] ------------ last change log update ;;; Version 2.3.2 Better error checking for ill-structured :local-only-slots declarations. Fixed DESTROY-CONSTRAINT to keep the update-slot bit of the slot. The old version incorrectly used to reset the bit. [6-28-1993 Dario Giuse] Moved the macro DEF-KR-TYPE to kr-macros.lisp, from kr.lisp. Added the documentation string David Kosbie suggested. Exported DEF-KR-TYPE from the KR package. Added David Kosbie's change to add-new-type, with modification to get a symbol name (rather than a string) for things like KR-BOOLEAN. Added fix from BVZ to COPY-FORMULA, to make sure that meta-information is copied properly from the formula being copied. Fixed problem with S-TYPE on slots that had no value (used to cause a warning about no-value not being a valid object of the type). [6-25-1993 Dario Giuse] Better checking for destroyed objects in destroy-slot. [6-24-1993 Dario Giuse] Bound *print-length* in the function used by PS, so large arrays which are values in slots are truncated after 10 elements. This is the same as what the printer does when it prints such arrays at the top level. [6-22-1993 Dario Giuse] Changed the KR-SEND macro so it no longer traps the binding of the symbol SCHEMA. [6-17-1993 Dario Giuse] Fixed problem with macroexpansion of a multi-level GV (or GVL), which caused things to fail if one of the slot names was not a keyword but a variable containing a keyword. [6-10-1993 Dario Giuse] A multi-level S-VALUE now gives a better error message when one of the intermediate slots contains a value which is not a schema. Giving a non-schema object or a null object to S-VALUE (through a multi-level S-VALUE) now produces a better error message. Giving a non-schema object to G-VALUE and GET-VALUE (either directly or in a multi-level G-VALUE) now gives a better error message. [6-9-1993 Dario Giuse] Created the new function KR::ADD-UPDATE-SLOT, which allows slots to be declared (or undeclared) as update-slots dynamically, after create-instance. In addition to setting (resetting) the internal bit, the function also modifies the :update-slots slot accordingly. Syntax: (kr::add-update-slot object slot &optional (turn-off nil)) The default is to make be an update slot. If is non-nil, however, the slot is changed to no longer be an update slot. [6-7-1993 Dario Giuse] Fixed a problem with destroyed formulas being kept around in their parent formula's list of children. This was causing formulas to disappear mysteriously under certain conditions. The bug was reported by Francesmary Modugno. Added the non-exported function I-DEPEND-ON, which returns a list of dotted pairs (schema . slot) for all slots upon which a certain formula depends. Merged in David Kosbie's changes for speedup. [5-26-1993 Dario Giuse] Fixed iterate-slot-value, which was broken for the case T nil nil. Changed (and extended) the regression test suite correspondingly. Added conditionally compiled code for the HP, where the function REALP seems to be undefined. [5-25-1993 Dario Giuse] First version with the new optimized internal representation. The distinction between special and non-special slots has been removed. All slots are stored in a certain number (currently 8) of bins in a schema. Each bin contains a list of slot structures. The bin for each slot is determined from the first character of the slot's printname, looking up an array that tells what bin to use. This change is user-invisible, except for the considerable speedups. [5-24-1993 Dario Giuse, David Kosbie] ;;; Version 2.2.2 Fixed meta-slot creation for formulas so that if a formula supplies some meta slots at creation time, and it also has a parent which supplies other meta slots, the final meta schema correctly inherits the parent's slots when needed. [4-23-1993 Dario Giuse] Added BVZ's fix to destroy-slot for the case where a formula that depends on the slot being destroyed is not attached to a schema. [4-20-1993 Dario Giuse] Fixed a problem with destroy-slot that could cause dependencies to destroyed formulas to be kept around after the slot was destroyed. This bug was reported by Brad Vander Zanded. [4-19-1993 Dario Giuse] Made MAKE-INTO-O-FORMULA return the formula it is given as argument. [4-6-1993 Dario Giuse] Added error message for improper schema in GV and GVL. Better error message when GV is given a non-schema. [3-29-93 Dario Giuse] Fixed storage leakage problems and time problems in IS-A-P type declarations. Merged the SCHEMA-P check with the SATISFIES check, which eliminates unnecessary consing. [3-29-93 David Kosbie] Fixed bug in CALL-ON-PS-SLOTS: the supplied function was being called with one argument too few when the object was a formula. Remember to modify KR documentation about "create-instance copies the formula down into the instances". This should be clarified; at the very least, there should be a pointer to some place that explains that in reality, formulas are only copied when requested, and in any case setting a value locally forces the formula never to be inherited. [3-23-1993 Dario Giuse] The function PS now returns the object it was given. This allows the interactive expression * to be used after an object is printed. The new, non-exported macro WITH-DEPENDENCIES-DISABLED can be used to prevent the evaluation of GV and GVL inside formulas from setting up dependencies. Inside its body, GV and GVL effectively behave (temporarily) like G-VALUE. The variable kr::*slot-setter-debug* may now be bound to a function, to be called every time the value of a slot is set. This occurs because of S-VALUE, formula evaluation, inheritance changes, or slot destruction. If the value has a non-nil value, the value should be a function of four arguments: #'(lambda (schema slot new-value reason) ...) The is a keyword that describes what event triggered the function. Note that there may be only one such function at a time, and it is not possible for an object to use a different function. Therefore, this is an inefficient mechanism which should be used ONLY for debugging purposes. [3-22-1993 Dario Giuse] Modified S-TYPE to return the type it was given, rather than NIL. This is more compatible with S-VALUE. [3-18-1993 Dario Giuse] Created a new non-exported function, CALL-ON-ONE-SLOT, which works like CALL-ON-PS-SLOTS but for a single slot in a schema. Syntax: (call-on-one-slot object slot #'function) The parameters to the are the same as in CALL-ON-PS-SLOTS. This function returns T if the slot exists and the was called, and NIL otherwise. [3-16-1993 Dario Giuse] Added the new reader macro #f(), which is read as (o-formula ...). For example, this allows you to write (s-value a :left #f(gvl :top)) instead of (s-value a :left (o-formula (gvl :top))) Added one more built-in name to G-FORMULA-VALUE. Specifying :META as the slot name retrieves the meta-schema for the formula, is one exists, or NIL. Note that this does not attempt to inherit a meta-schema. [3-11-93 Dario Giuse] Added printing of meta-information when PS is given a formula. [3-10-93 Dario Giuse] Added a SETF form for G-LOCAL-VALUE, which simply expands into S-VALUE. Fixed new bug in CALL-ON-PS-SLOTS that was crashing when printing formulas. Change documentation for invalidate demon - need to clarify. [3-8-93 Dario Giuse] S-VALUE may now have more than one slot in its argument list. This is similar to G-VALUE: all slots but the last one are used to access objects, and then the value of the last slot specified is set in the resulting object. For example: (s-value item :parent :parent :left 100) sets the :left slot of the item's parent's parent to 100. An appropriate error message is given if any of the intervening objects is found to be NIL. [3-5-93 Dario Giuse] Made GV behave exactly like G-VALUE when used outside formulas. In other words, if there is no current formula, GV just calls G-VALUE and does not attempt to set up a dependency. Replaced kr-call-initialize-method in BEGIN-CREATE-INSTANCE with the more modern kr-init-method [3-4-93 Dario Giuse] Removed the definition of KR-BOOLEAN, which is now defined in the types file. [2-25-93 Dario Giuse] Rearranged things and used DEFVARs so it should now be possible to reload the file kr.fasl without having the type system choke when types are already defined. [2-24-93 Dario Giuse] Fixed the new version of PS to work properly with inheritable formulas that are invalid. Formulas are copied down, but their value is not recomputed. [2-23-93 Dario Giuse] Added a new function, CALL-ON-PS-SLOTS, which can be used to call a function on each slot that would be printed by PS. The arguments are as follows: (call-on-ps-slots schema function &key (control t) inherit (indent NIL) types-p all-p) The keyword arguments have the same meaning as in PS. The should be a function of 9 arguments, as follows: (lambda (schema slot formula is-inherited valid real-value types-p bits indent limits)) The is bound to each slot in turn. The is nil, for non-formula values, or the original formula in the slot. is T if the value in the was inherited. is nil if the contains a formula whose cached value is invalid. The is what g-value would return. If is T, the should process type information for the . The are the internal representation of the slot's features. is the level of indentation; is a number (the maximum number of values from the to process), or NIL if all values should be processed. [2-20-93 Dario Giuse] Generating an error message for type declarations that do not contain any slot names at all. Most often, this results from misplaced parentheses in the type declaration. Added support for the same syntax that is used for :CONSTANT slots to all other declaration slots (i.e., :IGNORED-SLOTS, :LOCAL-ONLY-SLOTS, :MAYBE-CONSTANT, :PARAMETERS, :OUTPUT, :SORTED-SLOTS, :UPDATE-SLOTS). This allows things such as: (create-schema 'a :declare (:parameters :left :top :width) (:update-slots :left :top)) (create-instance 'b a :declare (:parameters T :except :width) (:update-slots T :height)) which behave the same as :CONSTANT declarations (except they do not use the :MAYBE-CONSTANT slot, of course). So, the following would happen: (get-declarations a :parameters) ==> (:left :top :width) (get-declarations b :parameters) ==> (:left :top) (get-declarations b :update-slots) ==> (:height :left :top) [2-19-93 Dario Giuse] Fixed problem with setting a value (with S-VALUE) in a slot which had a type declaration, but no value. This used to destroy the type declaration, because GET-VALUE was incorrectly used by CHECK-SLOT-TYPE. [2-8-93 Dario Giuse] Fixed check-slot-type to actually ignore the new value if the user decides to continue after the error message is given. [2-4-93 Dario Giuse] Added better error checking for cases like (create-instance nil 'PROTO) where the prototype name is quoted. Fixed GET-TYPE-DOCUMENTATION, which had gotten mangled and gave an array index error. [1-21-93 Dario Giuse] Fixed the bug with (create-schema 'A nil (:left 10)), which used to create a slot named NIL with value NIL. This is true of any slot specifier: NIL is not allowed in any position. [1-19-1993 Dario Giuse] Enabled the #k<...> macro reader by default. To turn it off, push the keyword :NO-K-READER onto the *features* list. [1-15-1993 Dario Giuse] Added :OUTPUT as a valid slot declarations. This is similar to the :PARAMETERS declaration, and is meant to allow users to declare slots that are computed by formulas and provide useful output values in an object. Created a reader macro for the #k<...> notation, which is produced when *print-as-structure* is non-nil. This macro allows the thing to be read back in as a KR object. Eliminated the new version of CHECK-SLOT-TYPE, which allowed multiple restarts. This version used some CLTL-II functions that turned out to be extremely expensive. [1-12-1993 Dario Giuse] Added support for meta-slots, i.e., slots attached to a formula. This works by using a KR schema, which is stored in the formula if needed. The following supports meta-slots: G-FORMULA-VALUE formula slot This function returns the value of meta-slot for the . If the latter is not a formula, or the meta-slot is not present, the function returns NIL. If the inherits from some other formula, inheritance is used to find the meta-slot. As a convenience, the can be the name of an internal formula slot, i.e., one of the structure slots used by KR in handling formulas. Such slots should be treated as read-only and should never be modified by application programs. The built-in slot names are: :DEPENDS-ON (object, or list of objects, on which the formula depends) :SCHEMA (object on which the formula is installed) :SLOT (slot on which the formula is installed) :CACHED-VALUE (current cached value of the formula) :VALID (whether the formula is valid) :PATH (path accessor, if any) :IS-A (parent formula, or NIL) :FUNCTION (compiled formula expression) :LAMBDA (original formula expression) :IS-A-INV (child formula, or list of children formulas) :NUMBER (valid/invalid bit, and cycle counter; internal use only) S-FORMULA-VALUE formula slot value Sets the value of a meta-slot in a formula. Creates a meta-schema if needed. FORMULA and O-FORMULA now take, as additional parameters, slot specifications in the style of CREATE-INSTANCE. The slot specifications are used to create meta-information for the formula. Note that to do so, one has to specify the default initial value for the formula, which is also an optional parameter. For example: (o-formula (get-value a :top) NIL (:creator 'GILT) (:date "today")) creates a formula with two meta-slots, :creator and :date. [1-8-1993 Dario Giuse] Added the (non-exported) function MAKE-INTO-O-FORMULA, which modifies a formula created using FORMULA to look like it was created using O-FORMULA. This allows the formula to be dumped properly with save-gadget. It is possible to specify that the expression be compiled first. The syntax is: (make-into-o-formula formula &optional compile-p) [1-4-1993 Dario Giuse] Check-slot-type now allows the user to redefine the value in the slot, if desired. This means that the function now returns multiple values if error-p is non-nil, as follows: - if error-p is non-nil, returns multiple values: - a replacement value, if the user chose to continue and supply a replacement; T if no error; NIL otherwise; - one of the following: - T (if type error and the user did not supply a value), or - NIL (if there was no type error), or - :REPLACE, if a replacement value was supplied by the user. - if error-p is nil, returns a string describing what error condition was found. [12-21-1992 Dario Giuse] Added a new type, KR-BOOLEAN, which is equivalent to T. It allows a slot to contain NIL or anything else, but it can be used by editors to display a yes/no button for setting the value of slots of this type. [12-15-1992 Dario Giuse] Fixed S-TYPE to NOT give an error when the value in the slot is a formula. Added string documentations, i.e., human-readable messages, for types. These can be added using the new function SET-TYPE-DOCUMENTATION: SET-TYPE-DOCUMENTATION type string This function associates the to the type. When an error message which concerns the type is printed, the documentation string is printed in addition to the raw type. For example: (set-type-documentation '(integer 0) "non-negative integer") The documentation can be retrieved with GET-TYPE-DOCUMENTATION: (get-type-documentation '(integer 0)) ==> "non-negative integer" The error message for bad KR types now tells whether the bad type was found as a consequence of evaluating a formula. [12-14-1992 Dario Giuse] Modified PS to print out type information. Also, modified to print out slots that have been declared but have no value. The function PS now takes two more &key parameters: - :types-p if non-nil, type information for slots is printed out - :all-p if non-nil, even slots that have no value (but which have some attribute bits) are printed out. [12-8-1992 Dario Giuse] Changed macroexpansion of type declarations. The old expansion, which was incorrect, would replace types with their encoded number. However, this could not work, because encoded numbers may change for each session. The new macroexpansion leaves type specifiers alone, so the encoding will happen at load time rather than at compile time. Renamed the new type specifier from IS-A to IS-A-P. This does not create a conflict, and avoids exporting a different name from the KR package. It is also more mnemonic. Changes :declare syntax to use keywords, rather than symbols. This makes it unnecessary to export more symbols (such as TYPE and UPDATE-SLOTS) from the KR package. The new syntax, therefore, is: ... :declare ((:type (integer :left :top)) (:update-slots)) [12-4-1992 Dario Giuse] Added an error-p parameter to CHECK-SLOT-TYPE. This allows the function to return a string containing the error message, rather than raising an error. The default value of error-p is T, which causes an error. Modified things so declarations, in particular CONSTANT declarations, that appear in prototypes can be eliminated in instances by specifying an empty clause. For example, use the expression :declare ((TYPE) (CONSTANT)) in a create-instance to turn off all constants declared by the prototype and eliminate all type declarations. [12-2-1992 Dario Giuse] Added support for slot types and type checking. Slots can be declared to be of a certain type; if typechecking is enabled (i.e., if kr::*TYPES-ENABLED* is non-nil), KR checks the type when a slot is first created using CREATE-INSTANCE, set with S-VALUE, or reevaluated by a formula. Type declarations are normally inherited at create-instance time, so there is no need to specify them in every instance. To override a declaration from a prototype, specify a new type in the instance (the type specifier T, which means any type, can be used if you want to unrestrict the possible type of a slot). Note that the symbol NULL (not the symbol NIL!) should be used to specify that a slot may contain NIL. The syntax of type declarations in create-instance is as follows: (create-instance instance prototype :DECLARE (type type1 type2 ...) :DECLARE ((type type1 type2 ...) (type type1 type2 ...) (other-declaration decl1 decl2 ...)) slot-specifiers ...) The keyword :DECLARE introduces a declaration group (currently, only type declarations are supported). Each declaration group consists of a list of declarations; if only one is present, the outside parentheses may be omitted, as shown in the second line of the example. Each declaration, in turns, consists of a symbol (currently, only TYPE is supported), followed by one or more list. In the case of TYPE, each list is of the form (type-specifier list-of-slots) This declares that each slot in the list-of-slots is of the given type-specifier. For example: (create-instance 'rec opal:rectangle :declare ((type (vector :BOX) (integer :LEFT :TOP) ((satisfies plusp) :WIDTH :HEIGHT) ((or (satisfies schema-p) null) :PARENT) ((or integer null) :COUNT) ((member :yes :no) :VALUE) (list :IS-A)) (type ((or (is-a a-window) null) :WINDOW)) ;; equivalent of :update-slots mechanism (update-slots :LEFT :TOP :WIDTH :HEIGHT :VALUE)) :declare (type (list :IS-A-INV)) (:left (o-formula (+ (gvl :parent :left) (floor (gvl :width) 2)))) (:top 10)) The main (exported) functions that manipulate declarations are as follows: G-TYPE schema slot Returns the type information associated with the of the . S-TYPE schema slot type &optional (check-old T) Adds a type declaration to the in the . The should be a valid Lisp type declaration, such as INTEGER or (OR LIST SYMBOL). Normally, this function checks that the existing value in the meets the new type specification, and gives an error if this is not the case. The parameter may be set to nil to suppress this behavior; this should be used with caution, because it may leave the with a value that does not typecheck. CHECK-SLOT-TYPE schema slot value Checks whether the given is of the valid type for the in the . If not, raises a continuable error. This function is called automatically by KR when a slot is modified, so you shouldn't have to call it explicitly. GET-DECLARATIONS schema selector Returns a list of all the slots in the that have associated declarations of the type given by , which should be one of: :TYPE :CONSTANT :UPDATE-SLOTS :LOCAL-ONLY-SLOTS. If is :TYPE, the return value is a list of lists; for example, ((:LEFT (OR INTEGER NULL)) (:TOP (OR INTEGER NULL)) (:NUMBER FLOAT)) If is any other value, the return value is a list of the slots that have the corresponding declaration. GET-SLOT-DECLARATIONS schema slot Returns a list of all the declarations associated with the in the . The list consists of keywords, such as :CONSTANT and :UPDATE-SLOT, and (in the case of type declarations) a list of the form (:TYPE ...). For example, (get-slot-declarations a :left) ==> (:CONSTANT (:TYPE (OR INTEGER NULL))) IS-A object This is a new type declarations, NOT a function or macro. It can only be used within Lisp type specifiers. The can be any Garnet object. The type declaration is true of all objects that satisfy (is-a-p object), i.e., of all instances (direct or indirect) of the . The following, for example, might be the type specification for a :WINDOW slot: (s-type foo :window '(or (is-a opal:window) null)) [11-24-1992 Dario Giuse] ;;; Version 2.1.14 Changed CALL-PROTOTYPE-FUNCTION to use APPLY instead of FUNCALL, which was not correct. Thanks to Dave Kosbie for the bug report. [10-9-1992 Dario Giuse] Fixed problem with GV refusing :SELF as a valid first argument. [9-17-1992 Dario Giuse] Eliminated compilation warnings from unused SLOT variable in kr.lisp. This was caused by the macroexpansion of iterate-slot-value. Added increment of kr::*sweep-mark* to RECOMPUTE-FORMULA, a non-exported function that is used by some system code in Garnet. This ensures that formulas affected by this function are invalidated properly. Replaced BREAK with CERROR in all the G-VALUE related functions. This generates a true continuable error, and can be handled programmatically if so desired. Exported the symbol KR:SCHEMA, which may be used for type declarations and such. [9-14-1992 Dario Giuse] Split up all the macros in a separate file, named kr-macros.lisp. This file should be compiled and loaded before kr.lisp and constraints.lisp. [8-20-1992 Dario Giuse] ---- last change log update ;;; Version 2.0.11 Added checks for NIL objects in G-VALUE and related functions. [8-5-1992 Dario Giuse] Fixed bug in DESTROY-SLOT which prevented the inverse relation from being eliminated when a relation slot was destroyed. [7-29-1992 Dario Giuse] Added the new exported macro WITH-DEMON-ENABLED, which is similar to with-demon-disabled. It works identically, except of course that the demon is re-enabled if it had been disabled (either selectively or with with-demons-disabled). [7-28-1992 Dario Giuse] Fixed bug which caused the "...array is nil..." message in Lapidary. This used to happen when a never-evaluated formula referenced a slot though a link, and the schema involved in the link was destroyed. This is fixed by adding checks to the GV family of functions. Calling S-VALUE of a relation slot with a single value which is a valid schema still gives a warning, but then continues and sets the relation slot with a list of the one schema. [7-24-1992 Dario Giuse] Fixed bug in eliminate-formula which caused update to be invoked recursively. This bug, introduced in 2.0.1, caused the demon to be invoked when a formula was found constant and eliminated. [7-15-1992 Dario Giuse] DECLARE-CONSTANT does nothing if *constants-disabled* is set to T. This means that this function is a no-operation inside WITH-CONSTANTS-DISABLED. [7-14-1992 Dario Giuse] Creating a schema with the :override keyword makes sure that formulas that depend on the OLD values are properly invalidated. In the old code, they were not. Modified DECLARE for functions FORMULA and DESTROY-CONSTRAINT in kr.lisp, hoping to eliminate warnings from some compilers. [7-10-1992 Dario Giuse] GV now gives an error message if its first argument is a keyword. This is most likely the result of using GV instead of GVL. DESTROY-SLOT now runs the invalidate demon before deleting the slot. This ensures that the Update algorithm sees the change. Fixed :override in CREATE-INSTANCE so that the contents of the :IS-A-INV slot of the parent are not duplicated. [7-9-1992 Dario Giuse] ;;; Version 2.0.10 Fixed PS to work with formulas (they used to be skipped, after the change to SCHEMA-P). Made it possible for the is-a-inv slot of formulas (i.e., a-formula-is-a-inv) to contain single formulas, as well as lists of formulas. This reduces the storage for all formulas which have exactly one child. [6-23-1992 Dario Giuse] Added an optional parameter, INHERITED, to DOSLOTS. The parameter controls whether inherited slots should be cycled through, in addition to local slots. The default is NIL, meaning that only local slots are used. Fixed bug in DESTROY-SCHEMA which had been introduced in 2.0.8. [6-18-1992 Dario Giuse] Made SCHEMA-P return NIL when given a formula. [6-17-1992 Dario Giuse] Eliminate potential problem with shared formulas (which should never occur anyway). [6-3-1992 Dario Giuse] Added a call to MARK-AS-CHANGED inside DESTROY-CONSTRAINT. This means that dependents are notified even if the actual value remains the same. This feature is primarily needed by applications such as C32 and Lapidary, which need to know the difference between slots with values and slots with formulas. [6-10-1992 Dario Giuse] ;;; Version 2.0.8 Changed DO-SCHEMA-BODY to take a parameter for :override. This fixes the problem with :override in CREATE-SCHEMA actually causing two slots by the same name. Incorporate BVZ's changes for CHANGE-FORMULA, so the lambda slot is set properly. Fixed FIND-DEPENDENTS, and consequently GET-DEPENDENTS. The former was still using some obsolete code. [5-27-1992 Dario Giuse] Modified kr::GET-DEPENDENTS to always return a list, even if there is only one dependent. Note that the list is reused and should not be modified. [4-27-1992 Dario Giuse] Link constants are now disabled by default. They may be enabled by setting kr::*link-constants-disabled* to NIL. [4-22-1992 Dario Giuse] The function PS now makes sure that all inheritable values are actually inherited before printing out an object when the :inherit option is set. This means that the user always sees ALL inheritable values from all possible prototypes, no matter whether the values had actually been inherited already. [4-21-1992 Dario Giuse] ---- last change doc update Added a new mechanism, link constants. This is somewhat similar to the existing :CONSTANT slot, in that it allows the user to specify a list of slots. These slots are considered constant, however, only if they appear in a GV or GVL expression, and only if they are not the very last slot in the expression. The idea is that link constants can be used to declare certain paths that involve system-defined slots constant. For example, inside aggregates one can use this to specify that a formula be eliminated if it depends on a constant value which is reached via a path that consists entirely of :LINK-CONSTANT slots. This mechanism makes it unnecessary to declare all slots in the path constant, and therefore allows the user to change intervening slots (in a benign way, naturally) if needed. Added the new exported function DECLARE-LINK-CONSTANT, which takes an object and a slot. This is similar to declare-constant, except that it works for link constants. The only legal value for the second argument is a single slot name; T or other values are not allowed. [4-20-1992 Dario Giuse] Attempting to call DESTROY-SLOT on a constant slot now gives a continuable error, just like S-VALUE. [4-16-1992 Dario Giuse] The function PS now prints lists of values properly. Before, parentheses were not printed, which made it impossible to distinguish between single values and lists of one element. Added check in PS for the case when :IGNORED-SLOTS contains a single value rather than a list. [4-15-1992 Dario Giuse] Formulas that are evaluated and found constant are no longer eliminated if *constants-disabled* is true, i.e., if inside WITH-CONSTANTS-DISABLED. Fixed bug in copy-to-all-instances (formula pointers were not being set properly). [4-14-1992 Dario Giuse] Fixed bug in kr-send for objects with a locally-defined NIL method. This used to incorrectly invoke the prototype method. Fixed bug in PS (for :sorted option on a slot that is not present). [4-10-1992 Dario Giuse] Made KR code reentrant, eliminated global variables *slot-position* and *slot-array*. [4-9-1992 Dario Giuse] ;;; Version 2.0.7 Added non-exported function copy-to-all-instances, which is similar to a recursive s-value that works on a schema and ALL its instances, no matter whether local values are already set. This was requested by BVZ. [4-6-1992 Dario Giuse] Fixed bug in KR-SEND. [4-2-1992 Dario Giuse] Fixed call-prototype-method. The latest version would go into an infinite loop if A had no method, B (is-a A) had a method which used call-prototype, and C (is-a B) also had a method using call-prototype-method. [4-1-1992 Dario Giuse] Added the variable kr::*REDEFINE-OK* which can be used to turn off errors caused by create-instance redefining slots that were declared constant in a prototype. [3-20-1992 Dario Giuse] It is now illegal for create-instance to set the value of a slot that was declared constant in the prototype. Currently, this causes a continuable error. [3-19-1992 Dario Giuse] Reduced consing for CREATE-INSTANCE. [3-18-1992 Dario Giuse] Changed the :CONSTANT slot such that it is now possible to specify its contents using a formula, rather than a hard-wired list. Of course, the value of the formula is only used at instance creation time. [3-17-1992 Dario Giuse] Modified KR-SEND and CALL-PROTOTYPE-METHOD to handle the latter much faster. This is done by keeping track of the last place from which a method was inherited, allowing the search for the next method to start from the middle of the hierarchy rather than from the bottom. [3-16-1992 Dario Giuse] Rewrote create-schema and create-instance almost completely. The mechanism avoids consing for slot creation, using a reusable set of arrays instead. [3-11-1992 Dario Giuse] ;;; Version 2.0.6 Made recursive destroy of objects (which occurs when creating a named schema more than once) considerably faster. This is done by having the low-level code know that it is not necessary to maintain relations and their inverses in such cases, since everything will be destroyed anyway. [3-10-1992 Dario Giuse] Fixed bug with :NAME-PREFIX in create-instance. The syntax was broken, and made it impossible to specify the name prefix properly. The syntax is now the same as in create-schema: (create-instance nil prototype :name-prefix "MY-NAME" (...slots)) [3-9-1992 Dario Giuse] Better error checking for DESTROY-CONSTRAINT. If any of the children of the formula have already been destroyed, nothing bad happens. Other children are still destroyed as usual. [3-2-1992 Dario Giuse] Better diagnostics for the case where there is an extra ' in front of a constant list. Attempting to set a constant slot now results in a continuable error, i.e. a call to BREAK. Previously, there was no way to continue from the error. [2-20-1992 Dario Giuse] ;;; Version 2.0.5 Added check for null schema in S-VALUE. Modified the macroexpansion to generate less inline code and allow better checking. Created the non-exported function kr::GET-LAMBDA. Given a formula, it returns the expression that was used to create the formula (as a list). Given anything else, it returns NIL. Added BVZ's fixes to satisfy the Lucid compiler. Among others, changed the initial size of *reuse-formulas* and *reuse-slots* to 1, but kept the fill pointer to 0. Modified IS-A-P to handle formulas as well as schemata. Fixed bug in S-VALUE for the case when a formula was being installed on a slot that had dependents. This happened when the slot contained another unevaluated formula which caused a broken link throw (thanks to BVZ for the fix). [2-19-1992 Dario Giuse] The function PATH is now named KR-PATH. Actually, this is an old change, but the original description managed to disappear from the change log. Added some error checking in PROPAGATE-CHANGE. This code checks for formulas that are installed on destroyed schemata. Exported the function DECLARE-CONSTANT. It is now possible to use T as the second argument to DECLARE-CONSTANT. This means that all slots that were defined in :MAYBE-CONSTANT (if any) are declared constant for the schema. The syntax is (declare-constant schema T). Modified SCHEMA-P to do a better job of checking for destroyed objects. The function now returns T if the object is a schema AND it was not destroyed. Changed the way destroyed schemata (and formulas) are handled. Destroyed objects are now marked by setting their "slots" structure slot to nil. The advantage is that the old name remains around. Consequently, destroyed objects are now printed in a more informative way. For example, (create-schema 'a (:left 10)) (setf p a) ; store pointer to schema (destroy-schema a) (ps p) prints out: *DESTROYED*(was A) Also, reused storage in formula structures. The "a-formula-slots" structure slot, which was shared with the "schema" structure, was unused for formulas. It is now used to store "a-formula-number", through a macro definition. Destroying the formula sets this slot to NIL, which is fine. [2-13-1992 Dario Giuse] ;;; Version 2.0.4 Eliminated the setting of dependencies for constant slots (one case was not handled properly). Fixed a bug in DECLARE-CONSTANT. Fixed a bug in constant evaluation which caused formulas that had not been inherited always to be considered non-constant, even though they would, in fact, eventually become constant. [2-12-1992 Dario Giuse] Changed formula inheritance so that when a formula is inherited, it is made an instance of the prototype's formula. This saves some storage. [2-11-1992 Dario Giuse] Created a new, non-exported function named MOVE-FORMULA. It takes a formula from a slot in a schema and moves it to another slot in another schema. This function is needed because simply using something like (s-value new-schema new-slot (get-value old-schema old-slot)) creates a deadly situation, i.e., a formula which is stored in two slots at once. Syntax: (MOVE-FORMULA from-schema from-slot to-schema to-slot) [2-6-1992 Dario Giuse] Created a new function named DECLARE-CONSTANT. This function may be used to declare that a slot is constant AFTER instance creation time. The behavior is the same as if the slot had been declared in the :CONSTANT slot at instance creation time, although of course the change does not affect other formulas which might have been evaluated previously. The :CONSTANT slot is modified accordingly: the new slot is added, and it is removed from the :EXCEPT portion if it was originally declared there. Syntax: (DECLARE-CONSTANT schema slot) [2-6-1992 Dario Giuse] Modified s-value and create-instance to check for formulas that are already installed on another slot. This is an error, since a formula should only be installed on one slot at a time. [2-6-1992 Dario Giuse] ;;; Version 2.0.3 Fixed a bug in run-invalidate-demons which caused the incorrect demon (i.e., the demon from the original schema rather than the schema whose formula was becoming invalid) to be called. [2-5-1992 Dario Giuse] Modified the dependents portion of slots so that a single value (rather than a list) is stored if the slot is depended on by only one formula. [2-3-1992 Dario Giuse] Created a new function, kr::SLOT-CONSTANT-P, which tells whether a slot was declared constant or has been made constant through formula evaluation. Note that the function returns NIL for unevaluated formulas, even though they might become constant upon evaluation. SYNTAX: (kr::slot-constant-p schema slot) RETURNS: T if slot is constant, NIL otherwise [2-3-1992 Dario Giuse] Added the new macro WITH-DEMON-DISABLED, which is rather similar to WITH-DEMONS-DISABLED. While the latter disables all demons, however, the former takes a specific demon which is disabled; other demons are executed normally. Syntax: (with-demon-disabled demon &body body) Examples: (with-demon-disabled 'opal::rectangle-invalidate-demon ...) (with-demon-disabled (g-value foo :invalidate-demon) ...) [1-31-1992 Dario Giuse] Removed the obsolete variable *ALLOW-CHANGE-TO-CACHED-VALUE* [1-30-1992 Dario Giuse] The variable *debug-switch*, which controls the printing of debugging information, is now exported from the KR package. [1-30-1992 Dario Giuse] Created two new functions (actually, a macro and a function) to split the work of CREATE-INSTANCE. This can be used (by developers) to create complex objects that need special constant-slot processing. The following sequence demonstrates a possible application: (begin-create-instance 'inst complex-part (:left 13) (:top (o-formula ...))) (s-value inst :foo "BAR") (s-value inst :width 100) (s-value inst :constant (if ... '(:left :top :width) T)) (end-create-instance inst) The first half (i.e., the call to BEGIN-CREATE-INSTANCE) sets up the schema and the initial value of the slots. In the example, nothing is declared constant. Some slots are then set, including the :CONSTANT slot. The second half (i.e., the call to END-CREATE-INSTANCE) processes the constant declarations and then calls the :INITIALIZE method for the instanec. [1-30-1992 Dario Giuse] Trying to set a constant slot now generates an actual error. If the variable kr::*constants-disabled* is non-nil, however, nothing happens. This is the same variable that cab be used to turn off constant processing in CREATE-INSTANCE. [1-30-1992 Dario Giuse] Changed the mechanism for demon invocation. NOTE: this applies only to the invalidate demon; the pre-set-demon, which is unused in Garnet, is not affected. The demon is now stored in objects (typically, it is inherited), rather than stored in the local variable kr::*invalidate-demon*. If a demon is present in the :INVALIDATE-DEMON slot of an object, the demon is invoked. The check for invocation is as before, i.e., the demon is invoked only if the name of the slot that is being invalidated is present in the :UPDATE-SLOTS slot of the object. [1-30-1992 Dario Giuse] ;;; Version 2.0.2 The switch to control whether constant declarations are used is now called kr::*constants-disabled* . It may be bound to T to cause all constant declarations to be ignored. This includes turning off error checking for setting slots that are declared constant. [1-29-1992 Dario Giuse] ;;; Version 2.0.1 Added a new (non-exported) function, GET-DEPENDENTS. Given a schema and a slot, it returns the list of formulas which depend on the slot. Syntax: (GET-DEPENDENTS SCHEMA SLOT) The depends-on slot of formulas may now contain either a single schema or a list of schemata. This saves storage in the common case. [1-13-1992 Dario Giuse] Changed the syntax for constant slot declarations. Things are now as follows: - the :MAYBE-CONSTANT slot is used in prototypes to declare a list of slots which instances may want to declare constant. This should correspond to the user-settable "parameters" of a gadget, for example. This declaration, per se, has no effect. - the :CONSTANT slot is used at instance creation time to control which slots are actually marked constant. The syntax is: ( :constant [T] [ADD-SLOTS] [:except DELETE-SLOTS] ) - T, if specified, declares that all slots contained in the :MAYBE-CONSTANT slot (which is typically inherited from a prototype) should be declared constant. - ADD-SLOTS, if specified, is a list of slots which should be declared constant. If T was also specified, the two lists are merged. - if :EXCEPT is specified, all slot names which follow it are taken out of the list of constant slot. This mechanism allows the user to eliminate certain slots from the list which was specified in :MAYBE-CONSTANT. The following examples illustrate the use of the new syntax. (create-instance 'prototype NIL (:MAYBE-CONSTANT :left :top) (:width (o-formula (+ (gvl :left) 40)))) (create-instance 'inst-1 prototype (:CONSTANT T) (:left 12) (:top 100)) The first time (g-value inst-1 :width) is evaluated, the system will notice that the formula depends only on the constant slot inst-1.left, and will eliminate the formula. Afterwards, inst-1.width will contain the number 42, rather than a formula. (create-instance 'inst-2 prototype (:CONSTANT :slot-1 :slot-2 T :EXCEPT :left) (:slot-1 12)) Slots :top, :slot-1, and :slot-2 are declared constant. Slot :left is not, even though it appears in the prototype's :MAYBE-CONSTANT, because it is explicitly excluded via the :EXCEPT keyword. (create-instance 'example nil (:MAYBE-CONSTANT :left :top :width :height) (:CONSTANT T) (:left 12)) This example declares the :maybe-constant slot, which will be used by future instances, and also declares that the four slots should be constant in the EXAMPLE schema. [1-8-1992 Dario Giuse] ;; Version 2.0 Changed G-LOCAL-VALUE to work properly with the new formula inheritance scheme. When a formula is inherited from a prototype, it is now marked as inherited. However, G-LOCAL-VALUE used to fail on this, and returned nil. The fixes version evaluates the formula and returns its value. [1-6-1992 Dario Giuse] Changed create-instance to avoid copying formulas down at instance creation time. Fixed s-value. Setting a prototype slot now correctly changes the values of all the slots which inherited a value, even though the prototype slot contained a formula. [1-3-1992 Dario Giuse] Inherited formulas which are declared constant in the prototype are now destroyed after their are evaluated the first time. [12-12-1991 Dario Giuse] Significantly reduced the size of the code generated by CREATE-INSTANCE and GVL. The former now produces a function call; the latter produces more efficient, iterative code when all slots in a GV link are special slots. [12-10-1991 Dario Giuse] Fixed a problem with DOVALUES which caused a compilation error if the body of dovalues contained a (RETURN) statement. This was not working because of the special branch taken if the slot ended up containing a single value instead of a list. Made PS print the expression (i.e., the lambda slot) of formulas. Fixed the problem with gv-local. This happened because G-LOCAL-VALUE (which is used by gv-local) does NOT create an empty slot, and therefore the function SETUP-DEPENDENCY did not have any place to record the dependency. [12-3-1991 Dario Giuse] Eliminated the problem with IS-A-P which forced the file KR.LISP to have to be compiled twice. Simply moved that function to CONSTRAINTS.LISP. [12-2-1991 Dario Giuse] Added code for constant formulas. This code is, for now, conditionally compiled (on a #+SUICIDE switch). This supports the following extensions to the syntax: - a slot in create-schema or create-instance may be specified as, e.g., (:CONST :left 14) This declares the :left slot to be a constant. Formulas which only depend on constant slots are eliminated. (*** note - the name of this slot is now :CONSTANT) - the slot :MAYBE-CONSTANTS may be specified in prototypes. When this is done, the contents of the slot (which must be a list of slot names) are used to determined what slots in the INSTANCES of the prototype will be marked constant at instance-creation time. - the slot :NOT-CONSTANT-SLOTS may be specified in instances. If it is specified (its contents must be a list of slots), all slots mentioned in it are NOT marked constant, even if the prototype declares them as constant. This slot is NOT inherited - it must be present locally. (*** note - this last point is now obsolete) [11-25-1991 Dario Giuse] Fixed problem in demo-arith by eliminating the setting of a KR slot in a formula. This is no longer allowed in KR 1.5.1 [11-14-1991 Dario Giuse] Fixed the problem with leftbutton not working in demo-grow. This required setting the window formula to be invalid in the select-it interactor. Change is in interactors.lisp (in function Check-Required-Slots) [11-12-1991 Dario Giuse] Fixed FULL and PS to work properly when a value is a dotted pair. [11-8-1991 Dario Giuse] Sped up propagate-change and setup-dependency, by using a new function named find-dependents. ;; new version (from opal/update-basics.lisp): (defun update-slot-invalidated (gob slot save) (declare (ignore save)) (let* ((gob-update-info (g-local-value gob :update-info)) (the-window (if gob-update-info (update-info-window gob-update-info)))) (if the-window (if (eq the-window gob) ;; is this a window? (pushnew slot (win-update-info-invalid-slots (g-local-value the-window :win-update-info))) (and (not (update-info-invalid-p gob-update-info)) (make-object-invalid gob gob-update-info the-window)))))) [10-29-1991 Dario Giuse] Modified GV to work properly when a relation slot is used inside a path. For example, (gv :parent :components :left) works, even though the second slot returns a list of components. The fist component in the list is simply used. This provides backward compatibility. [10-20-1991 Dario Giuse] Added a switch, tentatively named *debug-switch*, which can be used to improve error checking in KR. Currently, this can be set to T to generate meaningful error messages within GV if a non-schema value is found in the middle of a path. [10-16-1991 Dario Giuse] Fixed the following problem: When a slot has a formula which evaluates to NIL, and when the slot is valid, it still shows the display as: :FOO = #k(nil . NIL) whereas it should be (NIL . T) [10-15-1991 Dario Giuse] Merged the two versions of G-VALUE-FN, improved generated code when schema is simply a symbol. [10-14-1991 Dario Giuse] Added a DEFVAR variable, kr::*store-lambdas*, which allows formulas to be stored without the lambda expression. The default, T, means to store the expression. This is a compile-time switch. [10-10-1991 Dario Giuse] Optimized propagate-change by using dependent-position instead of a full slot-accessor. [10-9-1991 Dario Giuse] ;;; Version 1.5.0 [Group of changes from Brad Vander Zanden follows:] 1. Changed code that handled cycles. Cycles are now detected using the strong connectivity algorithm given in Aho, Hopcroft, and Ullman on pp 189-195. Any strongly connected component of size greater than 1 is a cycle. Cycles of size 1 (i.e., a slot that depends on itself) are not labeled as cycles, but the dependencies are labeled as being part of a cycle, so everything works out. The code changes involved replacing check-priority and reorder, deleting validate-cycle, renumber-cycle, and invalidate, and adding a new function called reorder-formulas. 2. Changed the set-cycle-bit and set-valid-bit macros. They used to assume that the value parameter was either t or nil. They were changed so that the value parameter can be an expression that is computed at run time. 3. Changed the last parameter in a call to add-to-reeval from (cycle-p *current-formula*) to t. The call was in re-evaluate-formula. 4. Replaced a call to invalidate with a call to reorder-formulas in propagate. 5. Changed the last line of mark-as-changed from a call to propagate to a call to add-to-reeval. The add-to-reeval call adds the slot's dependents to the evaluation queue, ensuring that they will be evaluated the next time propagate is called. The original code did not add the dependents to the evaluation queue, so the change was never noticed. 6. Added a statement to g-value-inherit-values that add a formula to the evaluation queue if necessary. 7. Added a progn statement to destroy-slot that in the case of eager evaluation, resets a formula's fixed bit to nil and places the formula on the evaluation queue. This has the same effect as setting the formula's cache value bit to nil in lazy evaluation. Added a second statement earlier in destroy-slot that saves the eval-bit for a formula before it is s-valued with a value. 8. In update-inherited-values, I changed the behavior of the function if the inherited value is a formula. Instead of calling propagate and then extracting the value of the formula, I create an instance of the formula and store the instance in the inherited slot. This change occurred in two different blocks of code in update-inherited- values. In both cases, the statements: (progn (propagate) (setf value (cached-value value))))) were replaced by the statements: (progn (setf value (formula value)) (setf (a-formula-schema value) schema) (setf (a-formula-slot value) a-slot) (setf *eval-queue* (insert-pq value *eval-queue*))))) This is not completely correct, because it doesn't take the old value of the slot and store it in the new formula. [4-2-1991] Renamed to version 1.5.0, since 1.4 is being released. [3-26-1991 Dario Giuse] ; Version 1.4.2 Improved the error message when GV or GVL are mistakenly used without a formula wrapped around them. The message now explains what might have happened and shows the name of the last slot in the GV expression. [1-18-1991 Dario Giuse] First working version of 1.4.2 (without eager evaluation). The following are the main highlights: Storage for KR schemata is greatly reduced. Slots are represented in a completely new fashion. Multiple values are no longer supported (although some old functions are provided for backward-compatibility). All slots now store a single value, which of course may be a list of values. All relation slots store a list of schemata (i.e., the single value in the slot is a list). Local-only-slots is also handled as a list of lists. inheriting values from a slot with a formula now creates a copy of the formula. [1-15-1991 Dario Giuse] ; Version 1.4.1 Fixed METHOD-TRACE, which was hopelessly broken and had been so for a long time. [10-24-1990 Dario Giuse] ;;; version 1.3.24 Added the non-exported function INHERITED-P [9-12-1990 Dario Giuse] Fixed bug with (CREATE-INSTANCE NIL). [9-11-1990 Dario Giuse] Fixed DELETE-SCHEMA to do nothing if given a schema that was already destroyed. [9-11-1990 Dario Giuse] Fixed bug with setting formulas which depend on relation slots (this was a bug in REMOVE-FORMULAS, and was reported by Brad Vander Zanden). [9-7-1990 Dario Giuse] Modified KR-SEND to avoid infinite loops (when looking for a method) if there are loops in the inheritance hierarchy. This was causing problems in degenerate cases. [9-4-1990 Dario Giuse] Modified DESTROY-SCHEMA to call the :DESTROY method on the schema just before it gets rid of it. This was previously disabled because of the problems with infinite loops looking for a method, as described above. [9-4-1990 Dario Giuse] Fixed CREATE-SCHEMA so that the following would behave properly: (create-schema 'foo :override) in the case where foo was NOT a previously created schema. This code used to do nothing, i.e., the schema would not be created at all. [9-4-1990 Dario Giuse] ;;; version 1.3.23 Eliminated problem with the *debug-names* array (reported by Paul Werkowski). The array is now initialized to NIL elements. [9-4-1990 Dario Giuse] Added a new exported function, RECOMPUTE-FORMULA. This function takes a schema and a slot, and forces the formula in the slot to be recomputed. The change is then propagated and demons are fired as usual, exactly as if the formula had been recomputed because of a change in its depended values. The syntax is: (RECOMPUTE-FORMULA SCHEMA SLOT) If the does not contain a formula in the , nothing happens. [9-3-1990 Dario Giuse] Eliminated the change to MARK-AS-CHANGED (see 8-29-90), which apparently caused some compatibility problems. [9-3-1990 Dario Giuse] Modified MARK-AS-CHANGED so that when it is called on a slot which contains a formula, it immediately reevaluates the formula. This behavior is different from the previous one, which always left the slot itself unchanged. --- NOTE - this change was eliminated - see 9-3-1990) [8-29-1990 Dario Giuse] Fixed a couple of bugs in MARK-AS-CHANGED, including the one reported by Roger a while back. This bug meant that slots which had formulas depending on inherited values which should have been invalidated were not. [8-20-1990 Dario Giuse] Fixed CREATE-INSTANCE so that local overriding of slots which might be inherited but are declared as :local-only-slots does the right thing, i.e., the overriding value takes precedence. The macros GET-VALUE and GET-VALUES no longer retrieve values in :is-a-inv slots which are not local. This is equivalent to making the slot :IS-A-INV a :local-only-slots slot. Other functions may have to do the same thing, for consistency. [8-1-1990 Dario Giuse] Create-INSTANCE now uses a special slot in a prototype to control whether values should be inherited normally, or whether certain slots in the prototype are considered local only and therefore should NOT be inherited. The slot is called :LOCAL-ONLY-SLOTS; it should contain any number of lists, where each list consists of a slot name and T or NIL. If the second element of the list is T, the value of the slot in the prototype is copied into the instance, and inheritance is never used thereafter. Note that if the value in the prototype contains a formula, the formula is copied down. If, on the other hand, the second element of the list is NIL, the slot is never inherited, and it is created in the instance with the value NIL. The following example explains the different behaviors: (create-schema 'a (:left 15) (:top 21) (:width 32) (:local-only-slots '(:top T) '(:width NIL))) (create-instance 'b a) (g-value b :left) ==> 15 ; inherited (g-value b :top) ==> 21 ; instance slot was set to prototype value (g-value b :width) ==> NIL ; instance slot was set to NIL (s-value a :left 100) (s-value a :top 100) (s-value a :width 100) (g-value b :left) ==> 100 ; new value is inherited as usual (g-value b :top) ==> 21 ; value is unaffected (g-value b :width) ==> NIL ; value is unaffected [7-30-1990 Dario Giuse] CREATE-SCHEMA (and thus CREATE-INSTANCE) now destroy all old instances of a schema, in addition to the old schema itself, when they create the schema. For example, the code (create-schema 'a (:left 10)) (create-instance 'b a) (create-schema 'a (:width 43)) will destroy the instance B, as well as the old value of A. [7-30-1990 Dario Giuse] Added a (non-exported) function named KR-SEND-FUNCTION. This behaves the same as KR-SEND, but it is a function which can be funcall-ed. The syntax is the same as KR-SEND: (KR-SEND-FUNCTION schema slot &rest arguments) [7-30-1990 Dario Giuse] Exported the new function COPY-FORMULA, which may be used to create a copy of a formula which shares the same parent (if there is one) and the same initial value. This function is primarily intended for advanced users. [7-27-1990 Dario Giuse] Changed IS-A-P to return T if the two objects it is given are EQ. This means that (IS-A-P a a) now returns T; the old code used to return NIL. [7-23-1990 Dario Giuse] ;;; version 1.3.22 Fixed CHANGE-FORMULA to get rid of the second value in the :KR-FUNCTION slot. Since the function always makes formulas be like the result of FORMULA, rather than O-FORMULA, it would be incorrect to keep the second value around. Fixed EXPAND-ACCESSOR to eliminate program self-modification. The argument list of macros such as G-VALUE used to be self-modifying if it ended with a non-keyword argument, i.e., a position argument. This has been fixed. [6-27-1990 Dario Giuse] Fixed a bug in SET-VALUES. This caused (SET-VALUES ... NIL) to incorrectly eliminate the information that a slot was depended on by some formulas, and as a result formulas would not be reevaluated correctly afterwards. Added the internal function COPY-FORMULA, originally provided by Roger Dannenberg. This function is not exported. It copies a formula and keeps the same parent (if there is one) and the same initial value. [6-26-1990 Dario Giuse] Fixed the bug in G-VALUE-NO-COPY-DOWN which caused local :INITIALIZE methods to be ignored at instance creation time. This would cause incorrect behavior, since the parent method was always invoked first. [6-25-1990 Dario Giuse] ;;; version 1.3.21 DESTROY-SCHEMA now physically destroys formulas that used to be attached to slots of the schema. This didn't use to be case, but is by now perfectly safe. This means that old formulas can be garbage-collected. [6-15-1990 Dario Giuse] Modified CREATE-SCHEMA to work properly with variables whose value is NIL. This resulted in smaller code being generated for both CREATE-SCHEMA and CREATE-INSTANCE. [6-10-1990 Dario Giuse] ;;; version 1.3.20 Eliminated internal slot names from formulas. This means that internal slots (such as the schema slot) are accessed directly through structure accessors, and the corresponding "reserved slot names" (such as :KR-SCHEMA) have been eliminated. [6-6-1990 Dario Giuse] Trying to initialize a relation slot to a non-schema value produces a warning and the value is ignored. This used to go unnoticed, and would happen, for example, in the erroneous call (create-schema nil (:left 12) (:parent NIL)) [6-4-1990 Dario Giuse] ;;; version 1.3.1 The :INITIALIZE method is no longer copied down into every object. Inherited slots are normally copied down the first time they are inherited, and the same was happening to the :INITIALIZE slot. This, however, was creating unnecessary garbage, since the method is typically only used once. The method is now inherited, but not copied down. [5-7-1990 Dario Giuse] Started version 1.3.1, which optimizes storage. [5-1-1990 Dario Giuse] ;;; version 1.1.27 Added #+allegro (gc t) at the end of kr-compiler.lisp [4/12/90 Mitchell] In low-level-set-value, changed #'formula-p to #'a-formula-p because Lucid complains about formula-p being a macro. Removed :is-a and :update-slots from *formula-slots*. In fixed-path-accessor, added test that "current" exists and is large enough before doing elt on it. [4/3/90 Ed Pervin] Define the package "KR" for the TI Explorer in kr-loader.lisp and kr-compiler.lisp. New and improved mode lines at the top of each file. Changed copyright to 1989, 1990. [4/2/90 Ed Pervin and Robert Cook] Added a new, non-advertised function named PATH which implements immutable paths. The syntax is as follows: (path number list-of-slots) The easiest way to use PATH is as follows: (gvl :parent :parent :previous-item :left) should be replaced by (gv (path :parent :parent :previous-item) :left) All of the slots but the last one are moved inside PATH. This makes performance significantly better. The should be unique for the same path within each formula. For example, replace the formula (o-formula (+ (gvl :parent :parent :previous-item :left) (gvl :parent :parent :width))) with the formula (o-formula (+ (gv (path 0 :parent :parent :previous-item) :left) (gv (path 1 :parent :parent) :width))) Note that it is admissible to use the same number for identical paths within the same formula. So, for instance, replace (o-formula (+ (gv (path 0 :parent :parent :previous-item) :left) (gv (path 1 :parent :parent :previous-item) :width))) with: (o-formula (+ (gv (path 0 :parent :parent :previous-item) :left) (gv (path 0 :parent :parent :previous-item) :width))) (note that number 0 is used for both paths). [3-23-90 Dario Giuse] Rewrote the low-level structure accessors to correct a portability problem uncovered by the Lucid compiler. All accesses are now through actual structure accessors, rather than the previous (array-based) scheme. Regular access is unaffected; iterate-accessors is slightly slower for slots whose name is unknown at compile time. [3-21-90 Dario Giuse] Fixed the compilation problem (reported by ecp) caused by SETF not being defined for LOGBITP in certain Lisp compilers. [3-19-90 Dario Giuse] ;;; version 1.1.26 Fixed compilation problem with PATH in constraints.lisp [3-16-90 Dario Giuse] Added an exported function, DO-PRINTABLE-SLOTS, which is somewhat of a cross between DOSLOTS and PS. It takes a schema and a function, and applies the function to all the slots in the schema that would be printed by PS. Unlike DOSLOTS, then, DO-PRINTABLE-SLOTS knows about ignored slots, sorted slots, and all the other print-control options used by PS. The syntax is: (do-printable-slots schema function &key (control t) (inherit nil)) The is called with three parameters: the itself, the name of the slot, and either T (if the slot is inherited) or NIL (if the slot is local). The meaning of and is the same as for the function PS. Example: (create-instance 'r opal:rectangle) (do-printable-slots r #'(lambda (schema slot is-inherited) (format t ": ~S ~S ~S (~s)~%" schema slot (g-value schema slot) is-inherited))) prints out the four slots :IS-A, :VISIBLE, :FAST-REDRAW-P, and :UPDATE-INFO and ignores the slots :DEPENDED-SLOTS and :UPDATE-SLOTS. [3-14-90 Dario Giuse] More work on improving performance of formula evaluation [2-13-90 Dario Giuse] Fixed the bug in CREATE-SCHEMA which prevented the following code from working: (let ((the-name 'FOO)) (create-schema the-name)) [2-12-90 Dario Giuse] ;;; version 1.1.25 Fixed CREATE-SCHEMA to eliminate the compiler warning about schema variables being undefined. [1/31/90 Dario Giuse] Modified DESTROY-SLOT to not destroy formulas that depend on the slot being destroyed. The old version used to indiscriminately destroy dependent formulas; the new version simply invalidates them. This ensures that inheritance (or setting a new value) will correctly recompute the formulas. [1/30/90 Dario Giuse] Fixed CREATE-INSTANCE to give a warning when the :IS-A slot is specified in the slot list. The :IS-A slot specification is simply ignored. [1/30/90 Dario Giuse] Changed DESTROY-SCHEMA so that deleted schemata are now printed out as #k<*DESTROYED*> [1/30/90 Dario Giuse] Fixed DESTROY-SLOT to handle inherited values (including ones which are depended on by some formula) to be modified properly. Values are simply inherited again when needed. [1/30/90 Dario Giuse] Changed the default value of the :CONTROL option in PS. The default value is now T, which means that ignored slots are not printed by default (and, in general, all print control options inherited from the schema itself). [1/30/90 Dario Giuse] Fixed check-relation-slot so that relation slots are no longer inherited when their value is set. [1/29/90 Dario Giuse] Created and exported a new function, NAME-FOR-SCHEMA. Given a schema, this function returns its printable name as a string. Note that the returned string SHOULD NOT be modified by the caller. The string name does not use the #k<> notation, i.e., the pure name is returned. [1/28/90 Dario Giuse] Eliminated the interface definition for the obsolete function LINK-VALID-P, which was effectively removed several months ago. [1/3/90 Dario Giuse] Added a variable, KR::*WARNING-ON-EVALUATION*, which may be set to T to give a warning whenever a formula is evaluated. This may be useful for debugging. The default setting is NIL. [12/1/89 Dario Giuse] Added a variable, KR::*WARNING-ON-CIRCULARITY*, which may be set to T to give a warning whenever a circularity is detected. The default is NIL. [11/28/89 Dario Giuse] Modified GV and GVL so that the last parameter is only taken to be a value position if it is a number. Everything else is assumed to be an expression which computes a slot. This allows, for example, the following: (gvl :parent (gvl :which-slot)) which computes the value of the parent's slot whose name is contained in the local slot :which-slot [11/28/89 Dario Giuse] ---- last documentation update 10-23-1989 ---------- 1. Modified CREATE-SCHEMA to only print out the message about a schema being created during compilation. 10-9-1989 --------- 1. Fixed bug in PS (actually, in printing names of schemata whose parent was a formula). 2. (IS-A-P thing T) now returns true if is a schema. I.e., T acts as the top-level superclass. 10-2-1989 --------- 1. Unnamed schemata are now given names that have as a prefix the name of the schema's parent, rather than the string "S". This is intended to make it easier to understand what type of object an unnamed schema is. 2. The formula which caused a null link is now stored in a variable internal to the KR package (named *last-formula*). This variable is useful for debugging and, in particular, is used by Roger's debugging code. 3. The function PS has a different interface, which is based on keywords rather than optional parameters. The new syntax is: (PS schema &key control (inherit nil) (indent 0)) :control has exactly the same meaning as the old, optional parameter. :inherit may be set to T to cause PS to print out not only local slots, but also slots whose value has been inherited. Such slots are printed out in a distinctive format. :indent may be used to set an indentation level. This is only used by some of the debugging code and does not concern ordinary users. 4. CREATE-SCHEMA has an additional feature. It is now possible to create "unnamed" schemata with a name prefix. This causes the creation of automatic names where the prefix part of the name is given explicitly as a symbol or a string. The new syntax is (create-schema name [:OVERRIDE] [:NAME-PREFIX prefix] {slot-descriptor}*) For example, (create-schema nil :name-prefix 'AGGREGATE (:left 45) (:top 3)) ==> #k Note that these are not "unnamed" schemata in the true sense of the word. A name for such schemata is created immediately; this includes a symbol in the KR-DEBUG package, which is exported. Compare this with "true" unnamed schemata, which are created with (create-schema NIL); such schemata are never given any symbol name unless they are printed out. True unnamed schemata, therefore, are significantly cheaper than name-prefix schemata. 5. Fixed the problem with CREATE-INSTANCE which made it impossible to use a variable as the schema name. This bug prevented CREATE-INSTANCE from being used inside a function, for example, when the name of the schema to be created was supplied as a function argument. 8-22-1989 --------- 1. Fixed APPEND-VALUE, which had been broken in the conversion to 2.3 2. Fixed CREATE-INSTANCE to give an error when called with the same name for object and class. 3. kr::*print-as-structure* is now T by default; this causes all schema names to be printed with the #k<> notation. Setting kr::*print-as-structure* to NIL causes the pure symbol name to be printed instead. 8-2-1989 (Version 2.3) 1. SET-VALUES is now supposed to work properly with formulas (and thus it should be renamed to S-VALUES, really). SET-VALUES on the :IS-A slot, for example, is still known not to work properly. 2. It is now consider illegal to use (RETURN) to exit DOVALUES. DOVALUES has more options, including one that can be used inside formulas to cause the formula to be invalidated when the ENTIRE list of values which is iterated upon by DOVALUES is modified in any way. The new, complete syntax is as follows: (DOVALUES (variable schema slot &key (local nil) (result nil) (formulas T) (in-formula nil)) &body) The meaning of the options is: - :LOCAL : if non-nil, DOVALUES only examines local slots, and ignores values that might be inherited. The default is to access the slot no matter whether it is local or inherited. - :RESULT : specifies the value which is to be returned by DOVALUES. Normally, DOVALUES simply returns NIL. - :FORMULAS : the default is to obtain the value of each formula which appears in the slot. If :FORMULAS is nil, however, the formulas themselves are returns (this behavior is similar to that of GET-VALUE). - :IN-FORMULA : if this is non-nil, the DOVALUES may be used inside a formula and the formula is invalidated when the slot is modified in any way. This allows the proper behavior when a formulas needs to examine all values in a slot. Note that in this case the special keyword :SELF may be used as the name of the schema; this works exactly as in GV. An example of the latter usage of DOVALUES: (formula '(let ((is-odd nil)) (dovalues (value :SELF :components :in-formula T) (if (odd value) (setf is-odd T))) is-odd)) Note that it is possible to use DOVALUES inside a formula without specifying the :in-formula option, but in this case the formula would NOT be invalidated when the slot changes: for example, the code (formula '(let ((is-odd nil)) (dovalues (value :SELF :components) (if (odd value) (setf is-odd T))) is-odd)) would correctly compute the answer the first time the formula is evaluated, but would never be evaluated again. 3. G-VALUE may now be called with no slot names at all. This simply returns the schema itself: (g-value a) ==> a More interestingly, GV may also be called without any slot names (in which case it also returns the schema). The special name :self may be used, of course; this gives a standard idiom for a formula to obtain at runtime the name of the schema on which it is installed: (gv :SELF). 4. The special variable KR::*WARNING-ON-CREATE-SCHEMA* may be bound to NIL in order to prevent the usual warning when CREATE-SCHEMA is redefining an extant schema. This variable is mostly for internal use and is not exported. 5. GET-VALUES should be avoided and is superseded by DOVALUES. In KR 2.3 and following, GET-VALUES may be inefficient because it conses when called on single-valued slots. DOVALUES, on the other hand, never creates any garbage storage. The old idiom: (dolist (item (get-values schema slot)) ...) should be replaced by (dovalues (item schema slot) ...) ------------------- Changes required for the conversion to the new version of KR (i.e., KR 2.0) from old, keyword-based versions: 1. No schema name can be a keyword. Symbols can be used instead, and NIL can be used to create nameless schemata. Also, quoted symbols cannot be used as schema names. Therefore, write (create-instance foo ...) instead of (create-instance 'foo ...) Note that (create-instance foo some-class ...) automatically assigns the schema as the value of the variable FOO. This variable is also automatically proclaimed SPECIAL. Unnamed schemata, i.e., the result of (create-schema nil ...), are not given any name by default. If they are ever printed out, a name is created for them in the KR-DEBUG package and exported. After being printed, unnamed schemata become the same as regular schemata, i.e., the symbol in the KR-DEBUG package has the schema itself as its value. 2. All class names should be symbols, and they should be EXPORTED by the package where they are created. It is recommended that programs refer to class names through the package name, since this enhances readability. For example, all programs that use Opal should use opal:rectangle as the name of the class. This should be done even if the program actually does (use-package "OPAL"). 3. It is possible to create top-level classes by simply specifying NIL as the second argument to create-instance: (create-schema object nil ...) This makes OBJECT a new schema, and its :is-a slot will contain NIL. 4. It is no longer possible to use and reference schemata that have not been previously created. Try to access a non-existent schema will cause an error message. If you need top-level schemata, use create-instance with NIL, as described above. 5. The old version of KR used to be very casual about using NIL as a schema. The current version of KR still allows retrieving values from a NIL schema (for instance, when you do something like (g-value (g-value a :slot1) :slot2) and :slot1 contains NIL), but I am considering turning this "feature" off in the future for better error checking. In the meanwhile, all old code will still work. Setting values of a NIL schema, on the other hand, causes an error. 6. Some KR functions have been renamed. Here is a list of the renaming scheme: the-formula --> formula create-fresh-schema --> create-schema (default behavior) create-schema --> (create-schema :OVERRIDE ...) is-formula --> formula-p do-slots --> doslots remove-constraint --> destroy-constraint check-link --> link-valid-p schema-call --> kr-send call-parent-method --> call-prototype-method defmeth --> define-method meth-trace --> method-trace The following functions have been eliminated: delete-schema delete-slot create-slot get-slots get-all-slots do-all-values print-schema (its functionality is now part of PS) 7. Since schemata are now structures, it is no longer possible to use CASE (for instance) to discriminate among different schema types. The old code (case (get-value schema :IS-A) (opal:rectangle ...) (opal:window ...)) , for example, will no longer work. It MUST be replaced by something like (let ((type (get-value schema :IS-A))) (cond ((eq type opal:rectangle) ...) ((eq type opal:window) ...)) I am thinking about writing a little macro that does this, but for the time being, beware. 8. Local variables CANNOT have the same name as a class schema created by the same package. This is because the schema name is a special variable and thus it conflicts with local variable names. Note that there is no problem with class schemata created by other packages. 9. Unnamed schemata have an internally generated name which is an integer. If the variable kr::*intern-unnamed-schemata* is set to T (the default), a symbol by the proper name is automatically created as soon as an unnamed schema is printed (by PS, or otherwise). This means that: - unnamed schemata may be referenced just like any other schema; - unnamed schemata that have been printed will NOT be garbage collected, unless of course someone does an explicit DESTROY-SCHEMA on them. Symbols thus created are automatically interned and exported by the KR package. It is possible to have the system NOT create symbols this way. This makes referring to unnamed schemata a little more awkward, but it allows them to be garbage collected as needed. This can be achieved by setting kr::*intern-unnamed-schemata* to NIL. If this is the case, the following applies: Unnamed schemata are printed as S1234, for example, but their name IS NOT the symbol S1234. One can refer to schemata by number, but only when the reference is rather recent (since only recently printed unnamed schemata are kept in a cache). An internal function named S is available for this purpose: this function takes an integer and returns the corresponding unnamed schema, if the reference is recent enough, or NIL. 10. CREATE-RELATION has a slightly different syntax: the inverses are now a simple &rest list. Therefore, (create-relation :components nil '(:parent)) should now be written as (create-relation :components nil :parent) 11. Define-method now takes a KEYWORD, rather than a symbol, as the method name. For instance, (define-method :draw opal-rectangle ...) Also, define-method no longer creates an automatic macro with the same name as the method name. The method is created just as before. 12. Change-formula has a different syntax. It no longer takes a formula and an expression; instead, it takes a schema, slot, and an expression. For example, (change-formula box-12 :right '(+ (gvl :left) 10)) ---------------------------- Changes for version 2.1 1. A new macro, named O-FORMULA, is exported by KR. This is similar to FORMULA, except that: - the formula expression does not need to be quoted; - O-FORMULA arranges for the expression to be immediately compilable. This means that O-FORMULA in a compiled file causes the formula to be installed as a compiled formula. This makes formula evaluation significantly faster in many cases. Executing O-FORMULA in an interpretive environment, on the other hand, creates an interpreted formula. 2. The function COPY-SCHEMA has been eliminated altogether. 3. If the print-control schema passed to PS (or inherited from the object being printed) contains a non-nil :PRINT-AS-STRUCTURE slot, schemata which are values in some slot are printed with a structure syntax, which shows some of their slots. Exactly which slots are printed can be selected by setting the slot :PRINT-SLOTS in the print-control schema.