AtomImpl.Mesa. Note that BasicAtomImpl also exports values to Atom.mesa
Last Modified On January 17, 1983 1:37 pm by Warren Teitelman
DIRECTORY
AMBridge USING [TVForReferent],
AMTypes USING [Class, Range, UnderType, TVType, TypeClass],
Atom USING [emptyAtom, PropList, GetPName, GetPropFromList, PutPropOnList],
AtomsPrivate USING [AtomRec, UnsafeMakeAtom],
Convert USING [MapValue],
List USING [IsAList],
Rope USING [Length],
RTTypesBasic USING [EquivalentTypes, GetCanonicalType, GetTypeAttachment, PutTypeAttachment],
RTBasic USING [nullType, Type],
SafeStorage USING [NewZone]
AtomImpl: CEDAR PROGRAM
IMPORTS AMBridge, AMTypes, Atom, List, AtomsPrivate, Rope, Convert, RTTypesBasic, SafeStorage
EXPORTS Atom
= BEGIN OPEN Atom;
PropZone: ZONE ← SafeStorage.NewZone[]; -- This should be moved into Atom interface so can be shared.
Creating Atoms
MakeAtomFromString:
PROCEDURE [ref:
REF
READONLY
TEXT]
RETURNS[
ATOM] =
TRUSTED
{
IF ref = NIL THEN RETURN[Atom.emptyAtom]
ELSE RETURN[AtomsPrivate.UnsafeMakeAtom[LOOPHOLE[ref, LONG POINTER TO READONLY TEXT]]];
}; -- of MakeAtomFromString
gennum: LONG CARDINAL ← 10000;
genstr: REF TEXT ← NEW[TEXT[5]];
Gensym:
PUBLIC
PROC [c:
CHARACTER ← 'A]
RETURNS[
ATOM] =
{
GenSym1: PROC [c: CHARACTER] = CHECKED {genstr[i] ← c; i ← i+1};
i: NAT ← 0;
gennum ← gennum + 1;
Convert.MapValue[put: GenSym1, value: [unsigned[gennum]]];
genstr[0] ← c;
genstr.length ← i;
RETURN[MakeAtomFromString[genstr]];
}; -- of Gensym
property list operations 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: RTBasic.Type ← RTBasic.nullType, prop:
REF
ANY, val:
REF
ANY] =
{
OPEN AMTypes;
underType: RTBasic.Type = UnderType[type];
class: Class = TypeClass[underType];
typeInfo: REF TypeRecord;
IF class = ref
OR class = list
OR List.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: RTBasic.Type ← RTTypesBasic.GetCanonicalType[Range[type]];
typeInfo ← NARROW[RTTypesBasic.GetTypeAttachment[referentType]];
IF typeInfo =
NIL
THEN
{typeInfo ← PropZone.NEW[TypeRecord ← []];
RTTypesBasic.PutTypeAttachment[referentType, typeInfo]
};
typeInfo.forRefThis ← Atom.PutPropOnList[typeInfo.forRefThis, prop, val];
};
type ← RTTypesBasic.GetCanonicalType[type];
typeInfo ← NARROW[RTTypesBasic.GetTypeAttachment[type]];
IF typeInfo =
NIL
THEN
{typeInfo ← PropZone.NEW[TypeRecord ← []];
RTTypesBasic.PutTypeAttachment[type, typeInfo]
};
typeInfo.forThis ← Atom.PutPropOnList[typeInfo.forThis, prop, val];
}; -- of TypePutProp
TypeGetProp:
PUBLIC
PROC [type: RTBasic.Type ← RTBasic.nullType, prop:
REF
ANY, dereferenced:
BOOLEAN ←
FALSE, ref:
REF
ANY ←
NIL]
RETURNS[
REF
ANY] =
{
OPEN RTTypesBasic;
typeInfo: REF TypeRecord;
IF type = RTBasic.nullType
THEN TRUSTED {
IF ref #
NIL
THEN {
type ← AMTypes.TVType[AMBridge.TVForReferent[ref]];
dereferenced ← TRUE;
}
ELSE RETURN[NIL];
};
type ← RTTypesBasic.GetCanonicalType[type];
typeInfo ← NARROW[RTTypesBasic.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: RTBasic.Type, dereferenced:
BOOLEAN ←
FALSE]
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[RTTypesBasic.EquivalentTypes[IF dereferenced THEN type ELSE AMTypes.Range[type], CODE[AtomsPrivate.AtomRec]]];
};
Length:
PUBLIC
PROC [self:
ATOM]
RETURNS[
LONG
INTEGER] = {
-- number of characters in pname
RETURN[Rope.Length[Atom.GetPName[self]]];
};
END.