Values.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 25, 1986 3:47:50 pm PDT
Last Edited by: Jacobi July 28, 1986 1:10:38 pm PDT
Values provide a general means to store arbitrary properties to arbitrary types.
A propagation mechanism allows implementation of default values.
NIL values can not be stored; since the NIL result is used to trigger propagation.
Clients of this package must be aware that the implementation for a particular type might provide more operations on specific property mechanisms for that particular type. A particular type might even share a specific property mechanism with the implementation for this package. E.g. enumerations should be performed directly using the type specific mechanisms.
A registration mechanism allows packages to register keys to make sure no other package is using the same keys for different purposes.
This package invokes some type machinery.
Client usage and application registrations
NotRegisteredType:
SIGNAL;
If proceeded and not otherwise specified: acts as a no-op
ReRegistration:
ERROR;
Double registration with an incompatible registration key.
Store:
PROC [onto:
REF, key:
REF, val:
REF←
NIL];
stores a value using a key
val=NIL means remove entry
No such thing as automatic propagation
may raise NotRegisteredType
Fetch:
PROC [from:
REF, key:
REF, propagate:
BOOL←
TRUE]
RETURNS [val:
REF];
retrieve a stored value
returns NIL if not found
propagate: if a nil result is returned, we try to fetch again using Propagate
may raise NotRegisteredType
Insert:
PROC [onto:
REF, key:
REF, val:
REF]
RETURNS [done:
BOOL];
stores a value using a key, if no previous value is stored
done: no value was previously attached to key and operation is done
No such thing as automatic propagation
may raise NotRegisteredType
Propagate:
PROC [from:
REF]
RETURNS [to:
REF];
returns the place where to propagate, a reasonable place to find default values
returns NIL if no propagation is defined
may raise NotRegisteredType
RegisterKey:
PROC [key:
REF, registrationKey:
REF ← NIL];
This procedure allows to make sure that applications do not interfere; Registration is
absolutely necessary only for atoms; other types can be protected by not exporting them.
To be formal, the package declaring a key type specifies whether keys of this type need
registration or not.
registrationKey#NIL allows re-registration of the same key, if the previous registration
used the same registrationKey. Other re-registration raises ReRegistration.
To make usage of this package possible when registration can't be done (e.g. unknown
order of loading of clients) use atoms starting with a letter [capital] X. By convention
no atoms with this starting letter must be registered; but also no protection can be given.
Implementors usage
StoreProc: TYPE = PROC [onto: REF, key: REF, val: REF];
FetchProc: TYPE = PROC [from: REF, key: REF] RETURNS [val: REF←NIL];
InsertProc: TYPE = PROC [onto: REF, key: REF, val: REF] RETURNS [done: BOOLLSE];
PropagateProc:
TYPE =
PROC [from:
REF]
RETURNS [to:
REF←NIL];
it better doesn't introduce loops...
RegisterType:
PROC [referentType: SafeStorage.Type, store: StoreProc ←
NIL, fetch: FetchProc ←
NIL, insert: InsertProc ←
NIL, propagate: PropagateProc ←
NIL, registrationKey:
REF ←
NIL];
registrationKey#NIL allows re-registration of the same key, if the previous registration
used the same registrationKey. Other re-registration raises ReRegistration.
If insert is defaulted, it is provided using fetch and store. The defaulted insert is monitored
against other calls of Insert; but it is not monitored against calls of Store. [But this should
suffice for clients to write correct initializations]