CDValueImpl.mesa (part of ChipNDale)
Copyright © 1983, 1987 by Xerox Corporation. All rights reserved.
Created by: Christian Jacobi, August 16, 1983 4:09 pm
Last edited by: Christian Jacobi, February 26, 1987 10:55:13 am PST
DIRECTORY
CDValue,
CD,
CDEvents,
RefTab;
CDValueImpl: CEDAR MONITOR
IMPORTS CD, CDEvents, RefTab
EXPORTS CD, CDValue =
BEGIN
Propagation: TYPE = CDValue.Propagation;
PrivateValueDRep: PUBLIC TYPE = RECORD [
values: RefTab.Ref
];
PrivateValueTRep: PUBLIC TYPE = RECORD [
registration: RefTab.Ref,
values: RefTab.Ref
];
globalTab: RefTab.Ref = RefTab.Create[];
registerTab: RefTab.Ref = RefTab.Create[];
registeredWithTechnology: REFNEW[INT];
DesignCreateEvent: CDEvents.EventProc = {
design.cdValuePriv ← NEW[PrivateValueDRep ← [values: RefTab.Create[]]]
};
TechnologyCreateEvent: CDEvents.EventProc = {
tech: CD.Technology = NARROW[x];
tech.cdValuePriv ← NEW[PrivateValueTRep ← [registration: RefTab.Create[], values: RefTab.Create[]]]
};
RegisterKey: PUBLIC ENTRY PROC [key: REF, boundTo: CD.Technology, registrationKey: REF] =
BEGIN ENABLE UNWIND => NULL;
Register: PROC [regTab: RefTab.Ref, key: REF, registrationKey: REF] RETURNS [ok: BOOL] =
BEGIN
oldRegistrationKey: REF ← RefTab.Fetch[regTab, key].val;
IF oldRegistrationKey=NIL THEN ok ← RefTab.Insert[regTab, key, registrationKey]
ELSE IF oldRegistrationKey=$nil OR oldRegistrationKey#registrationKey THEN ok ← FALSE
ELSE ok ← TRUE
END;
done: BOOLFALSE;
IF registrationKey=NIL THEN registrationKey ← $nil;
IF boundTo=NIL THEN done ← Register[registerTab, key, registrationKey]
ELSE {
done ← Register[registerTab, key, registeredWithTechnology];
IF done THEN {
tem: REF PrivateValueTRep = boundTo.cdValuePriv;
IF tem=NIL THEN RETURN WITH
ERROR CD.Error[ec: calling, explanation: "technology had not been registered"];
done ← Register[tem.registration, key, registrationKey]
};
};
IF ~done THEN RETURN WITH ERROR CD.Error[doubleRegistration]
END;
Fetch: PUBLIC ENTRY PROC [boundTo: REF, key: REF, propagation: Propagation] RETURNS [REF] =
BEGIN ENABLE UNWIND => NULL;
val: RefTab.Val; found: BOOL;
DO
WITH boundTo SELECT FROM
d: CD.Design => {
[found: found, val: val] ← RefTab.Fetch[d.cdValuePriv.values, key];
IF found THEN RETURN [val];
IF propagation>design THEN boundTo𡤍.technology ELSE RETURN [NIL]
};
t: CD.Technology => {
[found: found, val: val] ← RefTab.Fetch[t.cdValuePriv.values, key];
IF found THEN RETURN [val];
IF propagation>technology THEN boundTo←NIL ELSE RETURN [NIL]
};
ENDCASE => {
IF boundTo#NIL THEN
RETURN WITH ERROR CD.Error[calling, "CDValue.Fetch: bad boundTo type"]
ELSE {
[found: found, val: val] ← RefTab.Fetch[globalTab, key];
IF found THEN RETURN [val];
RETURN [NIL]
};
};
ENDLOOP
END;
GetTab: PROC [boundTo: REF] RETURNS [ref: RefTab.Ref] =
INLINE BEGIN
WITH boundTo SELECT FROM
t: CD.Technology => RETURN [t.cdValuePriv.values];
d: CD.Design => RETURN [d.cdValuePriv.values];
ENDCASE => {
IF boundTo#NIL THEN
RETURN WITH ERROR CD.Error[calling, "CDValue.Store: bad boundTo type"]
ELSE RETURN [globalTab]
};
END;
Store: PUBLIC PROC [boundTo: REF, key: REF, value: REF] =
BEGIN
ref: RefTab.Ref = GetTab[boundTo];
IF value#NIL THEN [] ← RefTab.Store[ref, key, value]
ELSE [] ← RefTab.Delete[ref, key];
END;
StoreConditional: PUBLIC PROC [boundTo: REF, key: REF, value: REF] RETURNS [done: BOOL] =
BEGIN
ref: RefTab.Ref = GetTab[boundTo];
IF value#NIL THEN done ← RefTab.Insert[ref, key, value]
ELSE done ← RefTab.Delete[ref, key];
END;
FetchInt: PUBLIC PROC [boundTo: REF, key: REF, propagation: Propagation, ifNotFound: INT] RETURNS [INT] =
BEGIN
WITH Fetch[boundTo: boundTo, key: key, propagation: propagation] SELECT FROM
r: REF INT => RETURN [r^]
ENDCASE => RETURN [ifNotFound]
END;
StoreInt: PUBLIC PROC [boundTo: REF, key: REF, value: INT] =
BEGIN
Store[boundTo: boundTo, key: key, value: NEW[INT ← value]]
END;
CDEvents.RegisterEventProc[$CreateNewDesign, DesignCreateEvent];
CDEvents.RegisterEventProc[$RegisterTechnology, TechnologyCreateEvent];
END.