DIRECTORY Pipal, PipalInt, PipalReal, RefTab; PipalOps: CEDAR DEFINITIONS = BEGIN enumerateMethod: Pipal.Method; EachChildProc: TYPE = PROC [child: Pipal.Object] RETURNS [quit: BOOL _ FALSE]; EnumerateProc: TYPE = PROC [object: Pipal.Object, each: EachChildProc] RETURNS [quit: BOOL _ FALSE]; HasEnumerate: PROC [object: Pipal.Object] RETURNS [BOOL]; Enumerate: EnumerateProc; CountChildren: PROC [object: Pipal.Object] RETURNS [count: NAT _ 0]; NthChild: PROC [object: Pipal.Object, rank: NAT _ 0] RETURNS [nthChild: Pipal.Object _ NIL]; Recast: PROC [object: Pipal.Object] RETURNS [Pipal.Object]; HashByEnumeration: Pipal.HashProc; CachedHashByEnumeration: Pipal.HashProc; EqualByEnumeration: Pipal.EqualProc; Reachable: PROC [root, candidate: Pipal.Object] RETURNS [BOOL]; AnyReachable: PROC [root: Pipal.Object, table: RefTab.Ref] RETURNS [BOOL]; replaceMethod: Pipal.Method; MapProc: TYPE = PROC [old: Pipal.Object] RETURNS [new: Pipal.Object _ NIL]; ReplaceProc: TYPE = PROC [parent: Pipal.Object, map: MapProc] RETURNS [newParent: Pipal.Object]; Replace: ReplaceProc; ReplaceFromRecast: ReplaceProc; ReplaceTable: TYPE = RefTab.Ref; ReplaceWithTable: PUBLIC PROC [oldRoot: Pipal.Object, table: ReplaceTable]; TransitiveReplace: PROC [root: Pipal.Object, table: ReplaceTable]; Path: TYPE = PRIVATE LIST OF PathBit; PathBit: TYPE = PRIVATE RECORD [type: PathBitType, rank: NAT]; PathBitType: TYPE = {ops, real, int}; ConcatPath: PROC [rootPath, childPath: Path] RETURNS [newPath: Path]; ExtendPath: PROC [currentPath: Path, type: PathBitType, rank: NAT] RETURNS [newPath: Path]; ApplyPath: PROC [root: Pipal.Object, path: Path] RETURNS [child: Pipal.Object]; ApplyRealPath: PROC [root: Pipal.Object, path: Path, transformation: PipalReal.Transformation] RETURNS [trans: PipalReal.Transformation, child: Pipal.Object]; ApplyIntPath: PROC [root: Pipal.Object, path: Path, transformation: PipalInt.Transformation] RETURNS [trans: PipalInt.Transformation, child: Pipal.Object]; ReplaceInPathWithTable: PROC [root: Pipal.Object, path: Path, table: ReplaceTable]; ReplaceInPath: PROC [root: Pipal.Object, path: Path, oldChild, newChild: Pipal.Object] RETURNS [table: ReplaceTable]; FindOpsPath: PROC [root, searched: Pipal.Object] RETURNS [path: Path, found: BOOL]; FindRealPath: PROC [rootTrans: PipalReal.Transformation, root: Pipal.Object, searchedTrans: PipalReal.Transformation, searched: Pipal.Object] RETURNS [path: Path, found: BOOL]; FindIntPath: PROC [rootTrans: PipalInt.Transformation, root: Pipal.Object, searchedTrans: PipalInt.Transformation, searched: Pipal.Object] RETURNS [path: Path, found: BOOL]; WatchDog: TYPE = PROC [arg1, arg2, arg3: REF _ NIL, registrationData: REF _ NIL]; RegisterWatchDog: PROC [event: ATOM, dog: WatchDog, registrationData: REF _ NIL]; ForgetWatchDog: PROC [event: ATOM, dog: WatchDog, registrationData: REF _ NIL, equal: PROC [REF, REF] RETURNS [BOOL] _ NIL]; Broadcast: PROC [event: ATOM, arg1, arg2, arg3: REF _ NIL]; replaceEvent: READONLY ATOM; ReplaceWatchDog: TYPE = PROC [root: Pipal.Object, table: ReplaceTable]; RegisterReplaceWatchDog: PROC [root: Pipal.Object, dog: ReplaceWatchDog]; ForgetReplaceWatchDog: PROC [root: Pipal.Object, dog: ReplaceWatchDog]; BroadcastReplace: PROC [table: ReplaceTable]; Event: TYPE = RECORD [message: Pipal.ROPE, state: REF]; Events: TYPE = LIST OF Event; UndoRedo: TYPE = RECORD [ undo: Events _ NIL, -- first undoable event head of list redo: Events _ NIL]; -- first redoable event head of list Do: PROC [old: UndoRedo, message: Pipal.ROPE, oldState: REF] RETURNS [new: UndoRedo]; UndoRedoOp: TYPE = PROC [old: UndoRedo, oldState: REF] RETURNS [new: UndoRedo, newState: REF]; Undo: UndoRedoOp; Redo: UndoRedoOp; Reset: UndoRedoOp; wDir: Pipal.ROPE; END. άPipalOps.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Bertrand Serlet May 17, 1988 2:26:51 pm PDT Louis Monier January 25, 1988 9:41:33 am PST Barth, January 29, 1988 3:42:40 pm PST Theory This module contains many low level operations which depend upon enumeration. Enumeration Enumerates all children of an object. Order of enumeration should be the same for to successive calls. Short cut for applying the enumerate method. If none then try PipalInt.Enumerate and then PipalReal.Enumerate. If both PipalOps and PipalInt (or a PipalReal) enumerations are supplied, the PipalOps enumeration should include all the objects enumerated by the PipalInt (or a PipalReal) enumeration. Returns the Nth child, 0 being of course the first child, NIL if no such child. Information-lossy way to convert to a "simpler" object. Uses Enumerate on children to compute hash. Same as previous, but caches its result. Uses Enumerate on children to decide whether equal. Transitive Closure Transitive closure is a common operation that has to be efficient. Is candidate object reachable by enumeration from the root object? Are any keys in table reachable by enumeration from the root object? Replacement new=old means no new object Replaces each child of parent which is mapped. TransitiveReplace guarantees that such a function will only be called if some child of parent is in map. A ReplaceProc can decide that even though some child changed, newParent is the same as parent. This is typically the case for objects which capture the notion of interface. Some child of parent should always be found in table although the implementation is not required to check this. Every source object class must implement this method. Simply applies the replace method once. No replace method => crash and burn. Does not propagate events nor do transitive closure. For use only with care. Information-lossy way to replace by replacing with the recasted object. Never use this for source objects! ReplaceTables map old objects to new ones. Same as Replace, but takes a table for convenience. table maps old objects to new ones. Replaces each old child by the corresponding new child everywhere reachable from root. Recursively replaces each parent and puts them into table. Path This section supports the specification of individual objects from a root. NIL designates the root. The list specifies the child of the root, then the child of the former, etc ... A more compact representation would be easy to introduce, of course. Only applicable if path#NIL AND path.first.type=real. Only applicable if path#NIL AND path.first.type=int. Replaces all the objects on the path from root to oldChild, and only those ones. ReplaceWithTable is called (no broadcast). A table is built during that descent. Returns the first ops path from root to child found, even if several would do. Returns the first real path from root to child found, even if several would do. Returns the first int path from root to child found, even if several would do. Events and Notification Events are analogoud to software interrupts. Some procedure might raise an event, which will cause all the registered handlers to be called. arg1, arg2, arg3: event-specific parameters passed through from Notify. registrationData: as given at registration. Can watchdog be applied twice? Registers a procedure which is called when a specific event occurs. Forgets a previously registered procedure. All parameters must be "equal" to registration parameters. If equal predicate is not given, pointer equality is assumed. Calls all registered WatchDogs. WatchDogs for a given event may be applied in any order. Replacement Event The replace event is called for all global replacement of objects. For that event, arg1 is a ReplaceTable. arg1 = table registrationData = parent Registers a replace WatchDog called whenever replace is broadcast. Short for RegisterWatchDog[replaceEvent, dog, parent] with the appropriate type convertions. Forgets a previously registered replace WatchDog. Parent must be identical to registration parent. Short for ForgetWatchDog[replaceEvent, dog, parent] with the appropriate type convertions. This procedure calls Broadcast. TransitiveReplace should be used for local replacement. Undo / Redo facilities Empties the redo list and stacks a new event containing state on the undo list. Undoes the last action, if any. Redoes the next action, if any. Undoes while possible. Hacks Directory where Pipal has been started. Shame on Cedar! Κƒ˜– "Cedar" stylešœ™Jšœ<™šœ œ˜%Kšœ™K™OK™DK˜—Kšž œœœ˜Ešž œœ.œœ˜[K˜—Jšž œœ"œ˜Ošž œœLœ8˜žJšœœœ™5—šž œœKœ7˜›Jšœœœ™4J™—Kšžœœ7˜Sšž œœDœ˜uKšœP™PK™QK™—šž œœ œœ˜SKšœN™N—šž œœ|œœ˜°KšœO™O—šž œœzœœ˜­KšœN™N——™šœ™M™—š œ œœœœœœ˜QKšœG™GKšœ+™+K™K˜—š žœœ œ#œœ˜QKšœC™CK™—šžœœ œ#œœ œœœœœœ˜|Kšœ₯™₯K™—š ž œœ œœœ˜