Page Numbers: Yes First Page: 1
Heading:
April 28, 1979 2:39 PM[IVY]<krl>document>str-basic-attach-old
? Triggering -- servants and demons
We need to think about the timing of when the demons are executed -- before and/or after the action, and how is timing determined on a set of related actions for a single Align?
Triggers
Each trigger (demon or servant) is indexed under a specific labelled anchor (unit and slot name). It is entered through a footnote on that anchor (or by being put on dynamically with the functions for manipulating the procedural attachment index).
Servants:
ToFind: Whenever a FindBinding goal is activated on an effective description which includes a mapDescriptor whose prototype for the focus slot includes a ToFind trigger, or it is in that slot of a pattern mapDescriptor, and if the goal is not immediately satisfied by the effective description, then the trigger code is executed. how is the result returned? Note that if the code does not end up satisfying the goal, and if on another cycle of the control loop the effective description is extended in any way, the trigger code will be tried again.
Note the two cases: Assume \$Foo.bar has a ToFind trigger. Then in the first case, the pattern is:
\A Foo with bar = @Do(’(Bind x Post))/ and the datum is:
\A Foo with mumble = .../.
In the second case, the pattern is:
\A Randomness with stuff = @Do(’(Bind x Post))/ and the datum is:
\A Randomness with stuff = The bar from a Foo with mumble = .../
ToEnumerate: Like ToFind, except for a FindList goal. Note that finding a primary anchor for a collection is different from being able to enumerate its elements.
ToMatch: Whenever an AlignMapDescriptor goal is activated and not immediately satisfied, the system looks for a ToMatch trigger assoicated with the focus slot of the prototype unit, and runs the code. As with ToFind, this will be tried each time the effective description is extended as long as the goal is not satisfied.
Demons:
WhenFilled: This trigger is activated whenever an action is taken meeting the following criteria:
1. A CoReference, LispPointer, or HandleDescriptor is added to an anchor which did not previously contain it
2. That anchor is the filler anchor for a perspective of the prototype for which the trigger is indexed, in a pair for the slot on which it is indexed.
Note that this covers several cases in adition to the simplest one. For example, it does not insist that the mapDescriptor have SELF as its focus slot. If we had in some anchor a previous description \The bar from a Foo/ and add the description \The bar from a Foo with mumble = 3/, a WhenFilled on \$Foo.mumble would be triggered. Also, there is no condition that the mapDescriptor appear at the top level of a labelled anchor. Thus if we have a datum of \A Foo with bar = A Gritch/ and add \A Foo with bar = A Gritch with yuk = "hello"/, then a WhenFilled on \$Gritch.yuk is activated. Part of the parameters avilable to the triggered code details need working out will include the appropriate anchors and focus slots.
WhenKnown: This trigger is activated whenever an action is taken meeting the following criteria:
1. A CoReference, LispPointer, or HandleDescriptor is added to an effective description which did not previously contain it
2. That effective description has as its structural grounding the filler anchor for a perspective of the prototype for which the trigger is indexed, in a pair for the slot on which it is indexed.
This is like WhenFilled, except that it is based on having inferred the identity, rather than having filled it into a structure. It can be used to have the system automatically store away the values of fillers (for selected slots of selected units) when they are deduced.
WhenEnumerationChanged: This trigger is like WhenFilled, except that the first condition is:
1. A change (addition or deletion) is made to an explicit enumeration descriptor appearing in an anchor, or a new enumeration descriptor is put into an anchor not previously containing one.
Note that this is structure local -- if something is described as \A Foo with bar = GoodGuys/ and \$GoodGuys.self contains an enumeration, then changes to that enumeration will not trigger a WhenEnumerationChanged on \$Foo.bar.
WhenDescribed: This trigger is activated whenever an action is taken meeting the following criteria:
1. Any change is made to the contents of an anchor
2. That anchor is lexically contained at any depth inside a filler anchor for the indexed slot in a mapDescriptor for the indexed unit
3. The change was made as part of a call to Align whose datum (including that added by describe -- see below) explicitly included the path down from the mapDescriptor to the changed anchor
Note that there is a big difference between a call to align which includes an action on some embedded anchor, and a sequence of two operations, the first of which finds and binds that embedded anchor, and the second of which does something to it. The single call will trigger all of the relevant WhenDescribeds on the chain down to the anchor, while in the separated case, the action will be taken without triggering any demons.
WhenDirectlyChanged: This trigger is like WhenDescribed, but operates only when a change is made at the top level of the filler anchor. how does this interact with folding -- should directness depend on the form of the call to Describe, or only on where the actual change was made?
WhenIdentified: This trigger is activated whenever a MapDescriptor with the index slot as focus slot and index unit as prototype is added to an anchor. It will not be triggered when one was already there, and simple folding prevented a new top-level mapDescriptor from being added. However it will be triggered if a second one is added because folding isn’t obvious (e.g. adding a second \The hometown from.../ descriptor to an anchor which has one).
Whereas all of the previous demons in this list were triggered because their attachment correspond to the structure in which changes were made, this one is triggered because it corresponds to the structure being added. Note that unlike WhenIdentified in KRL-0, it does not depend on the anchor to which it is being added being primary -- it is triggered when an appropriate descriptor is added to any anchor (including one embedded in a contingency) it is up to the trigger code to determine the nature of the place it is being added.
Traps
Each trap (demon or servant) appears in the meta-description of an anchor and is not otherwise indexed.
Servants
ToFind: Whenever a FindBinding goal is activated on an effective description which includes in its procedures a ToFind trap, and if the goal is not immediately satisfied by the effective description, then the trap code is executed. how is the result returned? Note that if the code does not end up satisfying the goal, and if on another cycle of the control loop the effective description is extended in any way, the trap code will be tried again.
ToEnumerate: Like ToFind, except for a FindList goal. Note that finding a primary anchor for a collection is different from being able to enumerate its elements.
Demons:
WhenFilled: This trap is activated whenever Coreference, LispPointer, or HandleDescriptor is added to the anchor on which it appears (note that it is not inherited by effective descriptions which copy its descriptors):
WhenEnumerationChanged: As with the trigger, mutatis mutandis
WhenKnown: When this anchor is the structural grounding of an effective description to which a Post is added
WhenDirectlyChanged: Any change is made at the top level of this anchor
WhenDescribed: Any change is made at any level (as qualified in the description of the corresponding trigger)
?. The Standard Tables
There are two types of signal tables available for use in matchtables:,complete tables (which have some response to every signal generated by the matcher); and fragments, which are designed to be appended to the front of a complete table. All are available as values of global variables. Complete tables have names ending with ST (signal table) and fragments with SF (signal fragment). Since tables are lists, the normal list structure operations work, e.g.:
(Align \A Foo with bar = @Do(’(Bind x Primary))/
\$F23.self
<! GiveFullAnswerSF ! UseTriggersSF ! SimpleMatchST>)
The angle brackets and bangs are CLISP’s. As written, this would cause the appending to be done once each time around. It would be better to bind some user named table to the result of the append once and for all.
How does this interact with the access compiler? can it handle anything which does not correspond to a single system-named table? Or can we impose some special convention by which it assumes that the value on the first time around will not change?
StructureMatchST: This is the default table in the editor, used for accessing and modifying the memory structures. Its main features are:
1. The effective description at every level of recursion into the pattern consists of only the datum structure directly -- no access is made to any other structures. Nothing is added to an effective description after its initial set-up, so the control loop is gone around only once.
2. The only goal for a pattern element is to find a single datum element which matches it structurally. This includes descriptors such as mappings for logical descriptors.
3. No use of trigger servants
4. No use of categories
5. Value returned is the complete binding list
Note that this match is really structural, NOT semantic. The pattern \A Foo with bar = Not(A Frob)/ will succeed against the datum \A Foo with bar = Not(A Frob with stuff = 3)/ but will fail against \A Foo with bar = A Bletch/ regardless of the incompatibility (including categories) of Frob and Bletch. Similarly, \Or(A Foo, ..., A Bletch)/ will succeed against \Or(A Foo with bar = 3, A Mumble, A Bletch) but will fail against either \A Foo/ (which is not an Or) or \Or(A Bletch, A Foo)/ (because the arguments are in the wrong sequence).
SimpleMatchST: This is the default table everywhere but the editor -- it is what you get with a NIL argument to Align, etc.. Its main features are:
1. The effective description at every level of recursion into the pattern consists of only the datum structure directly -- no access is made to any other structures. Nothing is added to an effective description after its initial set-up, so the control loop is gone around only once.
2. The only goal for a pattern element is to find a single datum element which matches it structurally. Logical descriptors in the pattern are treated as follows:
Or creates a simple split;
Not creates a subgoal and does the appropriate sign inversion;
SetOf looks for a SetOf descriptor in the datum and tries to match the argument to its argument, or a complete enumeration and sets up conjunctive goals of matching the argument to all of them. Same for SequenceOf.
This says what is done with these descriptors in the pattern. If found in the datum, they are ignored except as mentioned for matching SetOf
3. No use of trigger servants
4. Categories are checked
5. Value returned is the complete binding list
TryServantsSF: This is used with any match table to add the following effect:
1. At the appropriate places for probing traps and triggers for servants, they are tried. There is a signal for each one, so the user can exercise more control by consing more specific signal actions on in addition to this one.
TryDemonsSF: This is used with any match table to add the following effect:
1. At the appropriate places for probing traps and triggers for demons, they are tried. There is a signal for each one, so the user can exercise more control as well.
DescribeSF: This is used with any match table to add the following effects:
1. If the match ends because of lack of resources (not because of contradiction), and all of the bindings have been filled, then all of the material in the pattern and in effective descriptions not in the structural grounding is written into the structural grounding.
2. Actions are taken as through the match had succeeded
3. Demons are tried (i.e. this table includes the TryDemonsSF).
4. The value returned, type of expansion, use of goals, etc. is unaffected.
This is inconsistent with the examples above which use T as the value. What seems best?
CanMatchSF: This is used with any form of match table to add the following effects:
1. If the match ends because of lack of resources (not because of contradiction), the match is considered to have succeeded.
2. Actions are taken as through the match had succeeded
3. The value returned, type of expansion, use of goals, etc. is unaffected, except that if some of the bindings have not been filled, the binding lists returned will not include all of the variables.
Individual Signals
This entire section is very incomplete -- I just started writing them down in random order
Signals dealing with goals
AddingGoal: About to add a goal to the goal set. This means that it was not trivially satisfied (which it checks before actually building a goal data structure). It is the user hook for doing arbitrarily fancy things to the goal structure.
AddingDisjunctionForOr: The pattern contains an Or. One goal is set up for each branch and binding environment split if necessary.
AddingInverseForNot: The pattern contains a Not. A goal is set up for the inverse.
Signals dealing with extending the effective description
AttemptingExtension: About to try the extension phase of a control loop. Signal happens before any attempt to see whether extensions are possible. The simple match and structural match tables answer NOTOK to this, causing the rest of the signals in this section never to be generated. This is a simple point at which the user can test resources and decide whether to go on or not.
ExtendingDescription: About to try extending a specific ED. This is the user hook for doing extensions other than the ones the built in matcher knows about.
FollowingCoreferenceLink: A coreference in the ED is being followed by adding the contents of the anchor it points to to the Ed.
FollowingGroundedMapDescriptor: The ED contains a mapDescriptor which would be a valid grounding path argument for a Seek (i.e. it contains a coReference in one of its slot fillers recursively, including MemberOf) A Seek for an anchor will be done on it, and the result (if any) added to the ED.
DescribingPointer: The ED contains a LISP pointer descriptor, and a standard type-description of it (e.g. \An Integer/) will be added to the ED. If the user returns a descriptor or anchor handle, it will be used in place of the standard simple one.
DescribingHook: Like DescribingPointer, for a Handle descriptor.
UsingPrototype: The ED contains a MapDescriptor. The descriptors from the anchor for its focus slot are added to the ED, with appropriate substitution markers and changes of meta-description.
Signals dealing with contradictions
CategoryConflict: stuff
ConflictingIndividual: stuff
Signals dealing with finishing up the match
NoExtensions: On a cycle of the control loop, no extensions were made. This will always be the case if the response to ExtendingDescriptions is NOTOK. The response to this signal determines what to do in incomplete matches.
GoalSatisfied: The top level goal was satisfied, but none of the actions have been taken yet. If the answer is OK, it will proceed to do the actions.
ValueForAlign: Everything is done and it is time to return a value. It will return whatever comes back from this signal.