File: NutImpl.mesa
Contents: Implementation of Nut.mesa.
Created by: Rick Cattell on January, 1982
Last edited by:
Cattell on July 27, 1983 8:14 pm
Willie-Sue on July 11, 1984 4:22:36 pm PDT
Widom on June 14, 1984 2:02:54 pm PDT
Donahue on February 1, 1985 9:29:03 am PST
(Nut display and edit procedures do not return values -- they are now pure procedures)
Last Edited by: Butler, July 11, 1984 4:34:54 pm PDT
DIRECTORY
DB,
DBNames,
Nut,
Rope,
ViewerOps;
NutImpl:
CEDAR
MONITOR
IMPORTS DBNames, Rope, ViewerOps
EXPORTS Nut =
BEGIN OPEN Nut, DB;
Types and global variables
implementations: PUBLIC NutList ← NIL;
NutList: TYPE = LIST OF NutRecord ← NIL;
NutRecord: TYPE = REF NutRecordObject;
NutRecordObject:
TYPE =
RECORD[domain:
ROPE, segment:
DB.Segment, procList: ProcList];
the procList contains a stack of procedures for this domain
ProcList: TYPE = LIST OF ProcRecord ← NIL;
ProcRecord: TYPE = REF ProcRecordObject;
ProcRecordObject: TYPE = RECORD[display: NutProc, edit: NutProc];
NoRegistration: PUBLIC ERROR = CODE;
Exported procedures
Display:
PUBLIC
ENTRY
PROC[eName, domain:
ROPE, segment:
DB.Segment, parent: Viewer←
NIL] =
BEGIN
ENABLE UNWIND => NULL;
implRec: ProcRecord = FindImpl[domain, segment];
IF implRec = NIL THEN RETURN WITH ERROR NoRegistration[];
implRec.display[eName, domain, segment, parent ! ABORTED => CONTINUE];
END;
Edit:
PUBLIC
ENTRY
PROC[eName, domain:
ROPE, segment:
DB.Segment, parent: Viewer←
NIL] =
BEGIN
ENABLE UNWIND => NULL;
implRec: ProcRecord = FindImpl[domain, segment];
IF implRec = NIL THEN RETURN WITH ERROR NoRegistration[];
implRec.edit[eName, domain, segment, parent ! ABORTED => CONTINUE];
END;
Register:
PUBLIC
ENTRY
PROC[domain:
ROPE, segment:
DB.Segment, display: NutProc ←
NIL, edit: NutProc ←
NIL] =
Registers a display, create for given domain. These will supersede any previous non-NIL registrations for this domain.
BEGIN
implRec: ProcRecord = FindImpl[domain, segment];
procs: ProcRecord = NEW[ProcRecordObject ← [display, edit]];
IF display = NIL THEN procs.display ← IF implRec = NIL THEN NIL ELSE implRec.display;
IF edit = NIL THEN procs.edit ← IF implRec = NIL THEN NIL ELSE implRec.edit;
SetEntry[domain, segment, procs];
END;
Push:
PUBLIC
ENTRY
PROC[ domain:
ROPE, segment:
DB.Segment, display: NutProc ←
NIL, edit: NutProc ←
NIL] =
Registers a display, create, query, and/or notify proc for given domain. These will
supersede any previous non-NIL registrations for this domain.
BEGIN
implRec: ProcRecord = FindImpl[domain, segment];
procs: ProcRecord = NEW[ProcRecordObject ← [display, edit]];
IF display = NIL THEN procs.display ← IF implRec = NIL THEN NIL ELSE implRec.display;
IF edit = NIL THEN procs.edit ← IF implRec = NIL THEN NIL ELSE implRec.edit;
PushEntry[domain, segment, procs];
END;
SetSpawnedProperty:
PUBLIC
PROC [of: Viewer, is: Viewer]
RETURNS [previous: Viewer] ~ {
IF of = NIL OR of.destroyed THEN RETURN[NIL];
previous ← NARROW[ViewerOps.FetchProp[of, $LastSpawned]];
ViewerOps.AddProp[of, $LastSpawned, is];
ViewerOps.AddProp[is, $SpawnedParent, of];
};
GetSpawnedProperty:
PUBLIC
PROC [of: Viewer]
RETURNS [current: Viewer] ~ {
current ← NARROW[ViewerOps.FetchProp[of, $LastSpawned]];
IF GetFrozenProperty[current]
THEN {
ViewerOps.AddProp[of, $LastSpawned, NIL];
RETURN[NIL] } };
GetSpawnedParent:
PUBLIC
PROC [of: Viewer]
RETURNS [current: Viewer] ~ {
IF GetFrozenProperty[of] THEN RETURN[NIL];
current ← NARROW[ViewerOps.FetchProp[of, $SpawnedParent]] };
SetFrozenProperty:
PUBLIC
PROC [v: Viewer, new:
BOOL]
RETURNS [previous:
BOOL] ~ {
IF v = NIL THEN RETURN[TRUE]; -- the non-existent viewer is always frozen
{refFrozen: REF BOOL = NARROW[ViewerOps.FetchProp[v, $Frozen]];
IF refFrozen =
NIL
THEN
{previous ← FALSE; ViewerOps.AddProp[v, $Frozen, NEW[BOOL ← new]] }
ELSE {previous ← refFrozen^; refFrozen^ ← new} };
IF new THEN ViewerOps.AddProp[v, $SpawnedParent, NIL]
};
GetNutInfo:
PUBLIC
PROC[v: Viewer]
RETURNS[segment: Segment, domain, entity:
ROPE] = {
entity ← NARROW[ViewerOps.FetchProp[v, $EntityName]];
segment ← NARROW[ViewerOps.FetchProp[v, $Segment]];
domain ← NARROW[ViewerOps.FetchProp[v, $DomainName]]
};
CopyNutInfo:
PUBLIC
PROC[from: Viewer, to: Viewer] = {
ViewerOps.AddProp[from, $EntityName, ViewerOps.FetchProp[to, $EntityName]];
ViewerOps.AddProp[from, $Segment, ViewerOps.FetchProp[to, $Segment]];
ViewerOps.AddProp[from, $DomainName, ViewerOps.FetchProp[to, $DomainName]] };
SetNutInfo:
PUBLIC
PROC[v: Viewer, segment: Segment, domain, entity:
ROPE] = {
ViewerOps.AddProp[v, $EntityName, entity];
ViewerOps.AddProp[v, $Segment, segment];
ViewerOps.AddProp[v, $DomainName, domain]
};
ChangeName:
PUBLIC PROC[v: Viewer, newName:
ROPE] = {
ViewerOps.AddProp[v, $EntityName, newName] };
EntityNameForViewer:
PUBLIC
PROC [v: Viewer]
RETURNS [entityName:
ROPE] ~ {
segment: DB.Segment;
entity, domain: ROPE;
[segment, domain, entity] ← GetNutInfo[v];
RETURN[DBNames.MakeName[segment, domain, entity]]
};
GetFrozenProperty:
PUBLIC
PROC [v: Viewer]
RETURNS [current:
BOOL] ~ {
IF v = NIL THEN RETURN[TRUE]; -- the non-existent viewer is always frozen
{ refFrozen: REF BOOL = NARROW[ViewerOps.FetchProp[v, $Frozen]];
IF refFrozen =
NIL
THEN current ←
FALSE
ELSE current ← refFrozen^ }
};
SetEntry:
INTERNAL
PROC[domain:
ROPE, segment:
DB.Segment, procs: ProcRecord] =
Actually inserts new records into the implementation list
BEGIN
nut: NutRecord = GetNut[domain, segment];
IF nut =
NIL
THEN
implementations ← CONS[NEW[NutRecordObject ← [domain, segment, LIST[procs]]], implementations]
ELSE nut.procList ←
LIST[procs]
END;
PushEntry:
INTERNAL
PROC[domain:
ROPE, segment:
DB.Segment, procs: ProcRecord] =
Actually inserts new records into the implementation list
BEGIN
nut: NutRecord = GetNut[domain, segment];
IF nut =
NIL
THEN
implementations ← CONS[NEW[NutRecordObject ← [domain, segment, LIST[procs]]], implementations]
ELSE nut.procList ←
CONS[procs, nut.procList]
END;
DeRegister:
PUBLIC
ENTRY
PROC[domain:
ROPE, segment:
DB.Segment] =
Deregisters all procs for this domain
BEGIN
nut: NutRecord = GetNut[domain, segment];
IF nut = NIL THEN RETURN;
nut.procList ← NIL;
END;
Pop:
PUBLIC
ENTRY
PROC[domain:
ROPE, segment:
DB.Segment] =
Deregisters top procs for this domain
BEGIN
nut: NutRecord = GetNut[domain, segment];
IF nut = NIL THEN RETURN;
nut.procList ← IF nut.procList # NIL THEN nut.procList.rest ELSE NIL
END;
Support procedures
FindImpl:
INTERNAL
PROC[d:
ROPE, seg: Segment]
RETURNS[ProcRecord] =
Try to find an implementation for domain d in segment seg.
BEGIN
nut: NutRecord = GetNut[d, seg];
IF nut = NIL THEN RETURN[NIL]
ELSE IF nut.procList = NIL THEN RETURN[NIL] ELSE RETURN[nut.procList.first]
END;
GetNut:
INTERNAL
PROC[d:
ROPE, seg: Segment]
RETURNS[NutRecord] =
Looks for an exact match for d and seg.
BEGIN
FOR iL: NutList ← implementations, iL.rest
UNTIL iL=
NIL
DO
IF Rope.Equal[iL.first.domain, d] AND (seg = iL.first.segment) THEN RETURN[iL.first];
ENDLOOP;
RETURN[NIL];
END;
END.
Change Log:
Cattell on January 16, 1984 12:12 pm: passing NIL in for segment when registering means will take any segment.
Butler on June 4, 1984: Users can register their own defaults. They are no longer built in. NIL in the place of the domain and/or segment will register a default for a domain and/or segment.
Cattell on January 16, 1984 12:12 pm: passing NIL in for segment when registering means will take any segment.
Butler on June 4, 1984: Users can register their own defaults. They are no longer built in. NIL in the place of the domain and/or segment will register a default for a domain and/or segment.
Butler on June 26, 1984: Major Revision of code has been completed. Dependencies between Squirrel and Nut and whiteboards have been altered. Nut is now independent of Squirrel. The creation of all viewers is now done through NutViewer.
Donahue on July 12, 1984:
NutImpl is now a free standing implementation of Nut; it can be run independently of any other piece of Squirrel.