AMAtomImpl.Mesa.
Last Modified On May 13, 1983 10:34 am by Paul Rovner
DIRECTORY
AMAtom USING [],
AMList USING [IsAList],
AMBridge USING [TVForReferent],
AMTypes USING [Class, Range, UnderType, TVType, TypeClass],
Atom USING [PropList, GetPropFromList, PutPropOnList],
AtomPrivate USING [AtomRec],
SafeStorage USING [EquivalentTypes, GetCanonicalType, GetTypeAttachment, nullType, PutTypeAttachment, Type]
;
AMAtomImpl: CEDAR PROGRAM
IMPORTS AMBridge, AMList, AMTypes, Atom, SafeStorage
EXPORTS AMAtom
= BEGIN OPEN Atom, SafeStorage;
Property List Operations for types
the following provide property list operations on types. They are included here because this interface is really a combination of atoms and property list operations. and they are used in both streams as well as by the userexec. Note that using them will invoke the runtime type package.
TypeRecord: TYPE = RECORD[forThis: PropList ← NIL, forRefThis: PropList ← NIL]; -- describes type attachment. .
TypePutProp: PUBLIC PROC [type: Type ← nullType, prop: REF ANY, val: REF ANY] = {
OPEN AMTypes;
underType: Type = UnderType[type];
class: Class = TypeClass[underType];
typeInfo: REF TypeRecord;
IF class = ref OR class = list OR AMList.IsAList[underType: underType] THEN {
if type is a ref type, attach to referent as well, so that if you start with the ref, and therefore can only obtain type for its referent, will still be able to find the type attachment.. IF there were a way of getting to type REF FOO from type FOO, then this would be unnecessary because if you wanted to know whether REF FOO had a type attachment and you had a FOO in hand, you would simply construct that type.
referentType: Type ← GetCanonicalType[Range[type]];
typeInfo ← NARROW[GetTypeAttachment[referentType]];
IF typeInfo = NIL THEN
{typeInfo ← NEW[TypeRecord ← []];
PutTypeAttachment[referentType, typeInfo]
}; 
typeInfo.forRefThis ← Atom.PutPropOnList[typeInfo.forRefThis, prop, val];
};
type ← GetCanonicalType[type];
typeInfo ← NARROW[GetTypeAttachment[type]];
IF typeInfo = NIL THEN
{typeInfo ← NEW[TypeRecord ← []];
PutTypeAttachment[type, typeInfo]
}; 
typeInfo.forThis ← Atom.PutPropOnList[typeInfo.forThis, prop, val];
}; -- of TypePutProp
TypeGetProp: PUBLIC PROC [type: Type ← nullType, prop: REF ANY, dereferenced: BOOLEANFALSE, ref: REF ANYNIL] RETURNS[REF ANY] = {
typeInfo: REF TypeRecord;
IF type = nullType THEN TRUSTED {
IF ref # NIL THEN {
type ← AMTypes.TVType[AMBridge.TVForReferent[ref]];
dereferenced ← TRUE;
}
ELSE RETURN[NIL];
};
type ← GetCanonicalType[type];
typeInfo ← NARROW[GetTypeAttachment[type]];
IF typeInfo = NIL THEN RETURN[NIL];
RETURN[Atom.GetPropFromList[IF dereferenced THEN typeInfo.forRefThis ELSE typeInfo.forThis, prop]];
}; -- of TypeGetProp
Miscellaneous
IsAnAtom: PUBLIC PROC [type: Type, dereferenced: BOOLEANFALSE] RETURNS[BOOLEAN] = {
-- e.g. if x: TYPE = LIST OF REF ANY, and you obtain a tv for the first element of x, its type is of REF ANY. The only way to find out if this is an atom is to ask whether the type of its referent is the same as that of the type of the range of ATOM. This procedure does that for you. If dereferenced = TRUE, then x is a tv for the referent, and in this case the test is whether the type of x is the type of the range of ATOM.
RETURN[EquivalentTypes[IF dereferenced THEN type ELSE AMTypes.Range[type], CODE[AtomPrivate.AtomRec]]];
};
END.