PipalModify.mesa 
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bertrand Serlet January 26, 1988 1:22:24 am PST
Louis Monier January 25, 1988 9:41:33 am PST
DIRECTORY Pipal, RefTab;
PipalModify: CEDAR DEFINITIONS = BEGIN
Theory
This modules define how to modify Pipal "worlds".
World
World: TYPE = REF WorldRec;
WorldRec: TYPE = RECORD [
object: Pipal.Object,
state: REFNIL,
undoEvents: Events ← NIL, -- first undoable event head of list
redoEvents: Events ← NIL, -- first redoable event head of list
selected: LIST OF Pipal.Object ← NIL -- must be children of the object
];
Event: TYPE = REF EventRec;
EventRec: TYPE = RECORD [
message: Pipal.ROPE,
object: Pipal.Object ← NIL,
state: REFNIL
];
Events: TYPE = LIST OF Event;
Generic Operations on Worlds
Undo: PROC [world: World];
Redo: PROC [world: World];
Reset: PROC [world: World];
Undoes while possible.
Commit: PROC [world: World];
Flushes undoEvents and redoEvents.
Do: PROC [world: World, message: Pipal.ROPE, newObject: Pipal.Object ← NIL, newState: REFNIL];
Stacks a new event containing the current object and state on the undo list and modifies current state and object.
Transitive Closure
Transitive closure is a common operation that has to be efficient.
Reachable: PROC [root, candidate: Pipal.Object] RETURNS [BOOL];
Is candidate object reachable by enumeration from the root object?
ReachableFromRoots: PROC [roots: Pipal.Objects, candidate: Pipal.Object] RETURNS [BOOL];
Is candidate object reachable by enumeration from any root object?
Replacement
replaceMethod: Pipal.Method;
ReplaceProc: TYPE = PROC [parent: Pipal.Object, table: RefTab.Ref] RETURNS [newParent: Pipal.Object];
Replaces each child of parent found in table.
Table maps [old child] -> [new child].
No replaceMethod method => crash and burn.
If no child of parent is found in table, it is possible but not imperative that newParent=parent.
Replace: ReplaceProc;
Short cut for applying the replace method.
No replace method => crash and burn.
TransitiveReplace: PROC [oldRoots: Pipal.Objects, table: RefTab.Ref] RETURNS [newRoots: Pipal.Objects];
Replaces every child by its matching object everywhere reachable from oldRoots. Recursively replaces each parent. If no first is reachable from oldRoots then newRoots=oldRoots.
Temporary Hack ....
ReplaceInWorld: PROC [world: World, oldChild, newChild: Pipal.Object ← NIL];
Short cut for applying the replacing everywhere in world oldChild by newChild.
END.