FILE: Rosemary.mesa, from [Indigo]<Rosemary>Release>Rosemary.DF
last changed by Barth, June 9, 1983 11:08 am
Last Edited by: Spreitzer, September 15, 1983 10:24 am
This file gives the data structure for, and most Ops on, a Rosemary simulation.
DIRECTORY List, Rope, OrderedSymbolTableRef, VFonts;
Rosemary: CEDAR DEFINITIONS =
BEGIN
Familiar Types:
ROPE: TYPE = Rope.ROPE;
AList: TYPE = List.AList;
SymbolTable: TYPE = OrderedSymbolTableRef.Table;
Errors and Signals:
Warning: SIGNAL [msg: ROPE, data: REF ANYNIL];
Error: ERROR [msg: ROPE, data: REF ANYNIL];
InterfaceMismatch: ERROR [cell: Cell,
index: CARDINAL,
expected, got: SignalType];
Stop: SIGNAL [msg: ROPENIL, data: REF ANYNIL];
Raised by Test procs and breakpoints.
Specifying structure:
RegisterCellClass: PROCEDURE [className: ROPE, expandProc: ExpandProc ← NIL, ioCreator: IOCreator ← NIL, initializer: Initializer ← NIL, evalProc, testProc: EvalProc ← NIL, ports: Ports, ioTemplate: REF ANY ← Unspecified];
expandProc: ExpandProc
calls Create(Cell/Node) to describe structure.
ioCreator: IOCreator
Called to create IO data structure.
initializer: Initializer
May initialize IO.
Creates state if leafily.
evalProc: EvalProc
Copies newIO into oldIO, then (maybe) changes newIO.
testProc: EvalProc
Performs a test on the cell.
ExpandProc: TYPE = PROCEDURE [thisCell: Cell, initData: REF ANY];
IOCreator: TYPE = PROC [cell: Cell, initData: REF ANY];
Initializer: TYPE = PROCEDURE [cell: Cell, initData: REF ANY, leafily: BOOLEAN];
EvalProc: TYPE = PROCEDURE [cell: Cell];
Unspecified: REF ANY;
CreateTopCell: PROC [instanceName, className: ROPE, initData: REF ANYNIL, decider: ExpandDeciderClosure] RETURNS [cell: Cell];
interfaceNodes must be empty at the top
ExpandDeciderClosure: TYPE = REF ExpandDeciderClosureRep;
ExpandDeciderClosureRep: TYPE = RECORD [
Decide: ExpandDecider, otherData: REF ANY];
ExpandDecider: TYPE = PROC [cell: Cell, otherData: REF ANY] RETURNS [ExpandDecision];
ExpandDecision: TYPE = {Leaf, Inline, Nested};
Possible: PROC [cell: Cell, whatToDo: ExpandDecision] RETURNS [possible: BOOLEAN];
CreateNode: PROCEDURE [within: Cell, name: ROPE, type: SignalType ← NIL --means unspecified--] RETURNS [node: Node];
CreateCell: PROCEDURE [within: Cell, instanceName, className, interfaceNodes: ROPE, initData: REF ANYNIL] RETURNS [cell: Cell];
Specifying Behavior:
AddNodeWatcher: PROC [node: Node, watcher: NodeWatcher, priority: Priority ← 0];
RemoveNodeWatcher: PROC [node: Node, watcher: NodeWatcher, priority: Priority ← 0];
NodeWatcher: TYPE = RECORD [
notify: NodeNotifyProc,
clientData: REF ANYNIL];
NodeNotifyProc: TYPE = PROC [node: Node, clientData: REF ANY];
Priority: TYPE = [0..1];
0 is for ordinary mortals, like breakpoints
1 is for things like the display, which should be updated first
AddCellEventWatcher: PROC [cell: Cell, event: ATOM, watcher: CellWatcher];
RemoveCellEventWatcher: PROC [cell: Cell, event: ATOM, watcher: CellWatcher];
CellWatcher: TYPE = RECORD [
notify: CellNotifyProc,
clientData: REF ANYNIL];
CellNotifyProc: TYPE = PROC [cell: Cell, clientData: REF ANY];
Events raised by RosemaryImpl:
$Schedule when cell comes off or goes on or moves to head of schedule
$Eval   after EvalProc called
AddGlobalEventWatcher: PROC [event: ATOM, watcher: GlobalWatcher];
RemoveGlobalEventWatcher: PROC [event: ATOM, watcher: GlobalWatcher];
GlobalWatcher: TYPE = RECORD [
notify: GlobalNotifyProc,
clientData: REF ANYNIL];
GlobalNotifyProc: TYPE = PROC [clientData: REF ANY];
Popular events:
$Stop  End of long user-initiated activity
$Start  Begin of long user-initiated activity
Operations:
ScheduleCell: PROCEDURE [cell: Cell];
put it in the schedule of the structure it participates in;
a No-Op if already Scheduled.
All ancestor cells are also Scheduled.
Run: PROCEDURE [str: Structure];
Untill schedule empty, or...
stop: BOOLEAN;
To suspend all running, set this; when sampled, Stop will be raised.
SingleStep: PROCEDURE [str: Structure];
Remove one thing from Schedule and do it
Eval: PROC [cell: Cell];
Call this from inside a test proc to run the Cell (and do some random likage, so CALL THIS ONLY FROM WITHIN A TEST PROC).
AllowToModify: PROC [cell: Cell, modifier: ModifyProc, blindly: BOOLEANFALSE];
Copies newIO into oldIO, then calls modifier, then cleans up;
Embeds itself recursively up to the root.
If blindly, then newIO not copied into oldIO, and all ports are assumed to change.
ModifyProc: TYPE = PROC [cell: Cell] RETURNS [subtle: BOOLEANFALSE];
allowed to modify cell's output entries in newIO.
needn't first copy into oldIO.
Setting subtle forces the cell to be scheduled.
CleanUpAfterModify: PROC [cell: Cell];
compares newIO to oldIO, distributes and schedules from differences
Test: PROC [subject: Cell, parms: TestParms];
Calls the Cell's Test proc, possibly surrounded by SIGNAL Stop["About to eval/Just eval'ed", cell].
TestParms: TYPE = REF TestParmsRep;
TestParmsRep: TYPE = RECORD [
stopBefore, stopAfter: BOOLEANFALSE];
CellToStr: PROCEDURE [cell: Cell] RETURNS [str: Structure];
gives the structure this cell contains;
if this cell is an Inline expansion, it has to go recursively to parent
UpToReal: PROCEDURE [cell: Cell] RETURNS [realCell: Cell];
Returns nearest ancestor, or self, that is a Real Cell.
NotifyCellEvent: PROCEDURE [cell: Cell, event: ATOM];
NotifyGlobalEvent: PROCEDURE [event: ATOM];
Data Structure:
Cell: TYPE = REF CellRep;
CellRep: TYPE = RECORD [
name: ROPE,
class: CellClass,
nextInstance: Cell,
parent, leftChild, rightSibling: Cell,
firstInternalNode: Node,
internalNodes, components: SymbolTable,
interfaceNodes: NodeS,
other: AList,
type: CellType,
expansion: ExpandDecision,
realCellStuff: RealCellStuff -- non-NIL only for Real Cells
];
CellType: TYPE = {Real, Shadow};
RealCellStuff: TYPE = REF RealCellStuffRep;
RealCellStuffRep: TYPE = RECORD [
schedNext: Cell,
newIO, oldIO: REF ANY,
newIOAsWP, oldIOAsWP: WordPtr,
locked: BOOLEANFALSE,
initData: REF ANYNIL,
state: REF ANY,
eval: EvalProc,
schedWatchers, evalWatchers: CellWatcherList ← NIL];
notInSchedule: Cell;
This goes in the schedNext slot of an unscheduled cell.
CellWatcherList: TYPE = LIST OF CellWatcher;
Structure: TYPE = REF StructureRep;
StructureRep: TYPE = RECORD [
container, mirror: Cell,
schedFirst, schedLast: Cell,
locked: BOOLEANFALSE,
insideNodes: NodeS];
NodeS: TYPE = REF NodeSR;
NodeSR: TYPE = RECORD [nodes: SEQUENCE length: CARDINAL OF Node];
CellClass: TYPE = REF CellClassRep;
CellClassRep: TYPE = RECORD [
name: ROPE,
expand: ExpandProc,
ioCreator: IOCreator,
initializer: Initializer,
eval: EvalProc,
test: EvalProc,
ports: Ports,
ioWordCount: CARDINAL,
ioTemplate: REF ANY,
firstInstance: Cell];
Ports: TYPE = REF PortsRep;
PortsRep: TYPE = RECORD [
ports: SEQUENCE length: CARDINAL OF Port];
Port: TYPE = RECORD [
firstWord, wordCount: CARDINAL,
name: ROPE,
type: SignalType,
input, output: BOOLEANFALSE];
Node: TYPE = REF NodeRep;
NodeRep: TYPE = RECORD [
name: ROPE,
type: SignalType ← NIL,
visible: Socket ← [NIL, LAST[CARDINAL]],
unwriteability: INTEGER ← 0,
readers: SocketList ← NIL,
watchers: ARRAY Priority OF NodeWatcherList ← ALL[NIL],
next: Node ← NIL,
other: AList ← NIL];
SocketList: TYPE = LIST OF Socket;
Socket: TYPE = RECORD [cell: Cell, index: CARDINAL];
NodeWatcherList: TYPE = LIST OF NodeWatcher;
SignalType: TYPE = REF SignalTypeRep;
SignalTypeRep: TYPE = RECORD [
toRope: ToRopeProc,
fromRope: FromRopeProc,
init: TypeInitProc,
maxWidth: MaxWidthProc,
parseTest: TestParseProc,
unParseTest: TestUnParseProc,
typeData: REF ANY];
ToRopeProc: TYPE = PROCEDURE [where: WordPtr, typeData: REF ANY] RETURNS [rope: ROPE];
FromRopeProc: TYPE = PROCEDURE [rope: ROPE, where: WordPtr, typeData: REF ANY] RETURNS [success: BOOLEAN];
TypeInitProc: TYPE = PROC [where: WordPtr, typeData: REF ANY];
MaxWidthProc: TYPE = PROC [typeData: REF ANY, font: VFonts.Font] RETURNS [INTEGER];
TestParseProc: TYPE = PROC [rope: ROPE, typeData: REF ANY] RETURNS [success: BOOLEAN, testProc: TestProc, testData: REF ANYNIL];
TestUnParseProc: TYPE = PROC [testProc: TestProc, testData: REF ANY, typeData: REF ANY, subject: ROPE] RETURNS [rope: ROPE];
TestProc: TYPE = PROC [testData: REF ANY, where: WordPtr, typeData: REF ANY] RETURNS [passes: BOOLEAN];
WordPtr: TYPE = LONG POINTER TO CARDINAL;
cellClasses: SymbolTable;
roots: SymbolTable;
Exploring the Data Structure:
LongCellName: PROC [cell: Cell] RETURNS [ln: ROPE];
LookupCell: PROC [
path: LIST OF ROPE,
from: Cell ← NIL --NIL means first name names root--]
RETURNS [cell: Cell];
RootStructure: PROC [cell: Cell] RETURNS [str: Structure];
SocketToWP: PROC [s: Socket] RETURNS [wp: WordPtr];
GetIndex: PROC [ports: Ports, key: ROPE] RETURNS [index: CARDINAL];
notFound: CARDINAL = LAST[CARDINAL];
END.