DIRECTORY
Atom USING [PropList],
AtomsPrivate USING [GetAtom, AtomRec, EnumerateAtoms],
List USING [DottedPairNode],
Rope USING [ROPE, Text, FromChar],
SafeStorage USING [NewZone]
Types and constants
PropZone: ZONE ← SafeStorage.NewZone[];
NILNotAnAtom: PUBLIC ERROR = CODE;
emptyAtom: PUBLIC ATOM ← MakeAtom[""];
Atom:
TYPE =
REF AtomsPrivate.AtomRec;
bridge from opaque ATOM to concrete Atom as defined in AtomsPrivate
Creating Atoms
ATOMToAtom:
PROC [atom:
ATOM]
RETURNS [Atom] =
TRUSTED
INLINE {
RETURN[LOOPHOLE[atom, Atom]];
};
ATOMToPropList:
PROC [atom:
ATOM]
RETURNS [PropList] =
INLINE {
RETURN[NARROW[ATOMToAtom[atom].propList, PropList]];
};
MakeAtom:
PUBLIC
PROCEDURE [pName: Rope.
ROPE]
RETURNS[
ATOM] =
TRUSTED {
IF pName = NIL THEN RETURN[emptyAtom]
ELSE RETURN[AtomsPrivate.GetAtom[pName]];
}; -- of MakeAtom
MakeAtomFromChar:
PUBLIC
PROCEDURE [char:
CHARACTER]
RETURNS[
ATOM] =
TRUSTED {
RETURN[AtomsPrivate.GetAtom[Rope.FromChar[char]]];
}; -- of MakeAtomFromChar
property list operations (for atoms and types)
property lists are alists, rather than list of ref any, so that the property list functions do not have to check the type of each entry to make sure it is a dotted pair. When automatic narrowing arrives, then maybe want to just make property list a list of typed objects.
GetPropertyList:
PUBLIC
PROCEDURE [atom:
ATOM]
RETURNS[PropList] = {
RETURN[IF atom = NIL THEN NIL ELSE ATOMToPropList[atom]]; -- treat NIL as an atom for purposes of GetProp
}; -- of GetPropertyList
PutProp:
PUBLIC
PROCEDURE [atom:
ATOM, prop:
REF
ANY, val:
REF
ANY] =
{
IF atom = NIL THEN ERROR NILNotAnAtom;
ATOMToAtom[atom].propList ← PutPropOnList[propList: ATOMToPropList[atom], prop: prop, val: val];
}; -- of PutProp
PutPropOnList:
PUBLIC
ENTRY PROCEDURE [propList: PropList, prop:
REF
ANY, val:
REF
ANY]
RETURNS[PropList] =
{
lst: PropList ← propList;
lst1: PropList ← NIL;
UNTIL lst =
NIL
DO
IF lst.first.key = prop
THEN
BEGIN
lst.first.val ← val;
RETURN[propList];
END;
lst1 ← lst;
lst ← lst.rest;
ENDLOOP;
prop not found on property list
lst ← PropZone.CONS[PropZone.NEW[List.DottedPairNode ← [key: prop, val: val]], NIL];
IF lst1 = NIL THEN RETURN[lst]
ELSE IF lst1.rest = NIL THEN {lst1.rest ← lst; RETURN[propList]} -- add at end --
ELSE ERROR ; -- shouldnt happen
}; -- of PutPropOnList
GetProp:
PUBLIC
PROCEDURE [atom:
ATOM, prop:
REF
ANY]
RETURNS[
REF
ANY] =
{
IF atom = NIL THEN RETURN[NIL] -- treat NIL as an atom for purposes of GetProp
ELSE RETURN[GetPropFromList[propList: ATOMToPropList[atom], prop: prop]];
}; -- of GetProp
GetPropFromList:
PUBLIC
ENTRY PROCEDURE [propList: PropList, prop:
REF
ANY]
RETURNS[
REF
ANY] =
{
FOR lst: PropList ← propList, lst.rest
UNTIL lst =
NIL
DO
IF lst.first.key = prop THEN RETURN[lst.first.val];
ENDLOOP;
RETURN[NIL];
}; -- of GetPropFromList
RemProp:
PUBLIC
PROCEDURE [atom:
ATOM, prop:
REF
ANY] =
{
IF atom = NIL THEN RETURN;
ATOMToAtom[atom].propList ← RemPropFromList[ATOMToPropList[atom], prop];
}; -- of RemProp
RemPropFromList:
PUBLIC
ENTRY PROCEDURE [propList: PropList, prop:
REF
ANY]
RETURNS[PropList] =
{
lst, lst1: PropList ← NIL;
lst ← propList;
UNTIL lst =
NIL
DO
IF lst.first.key = prop
THEN
{IF lst1 = NIL THEN RETURN[lst.rest]
ELSE {lst1.rest ← lst.rest; RETURN[propList]};
};
lst1 ← lst;
lst←lst.rest;
ENDLOOP;
RETURN[propList];
}; -- of RemPropFromList
GetPName:
PUBLIC
PROCEDURE [atom:
ATOM]
RETURNS [pName: Rope.Text] =
{
IF atom = NIL THEN ERROR NILNotAnAtom;
RETURN[ATOMToAtom[atom].pName];
}; -- of GetPName
MapAtoms:
PUBLIC
PROCEDURE [proc:
PROC[atom:
ATOM]] =
TRUSTED {
proc1:
PROCEDURE [atm:
ATOM]
RETURNS[stop:
BOOLEAN] =
CHECKED {
proc[atm];
RETURN[FALSE];
}; -- of proc1
[] ← AtomsPrivate.EnumerateAtoms[callee: proc1];
}; -- of MapAtoms
FindAtom:
PUBLIC
PROCEDURE [proc:
PROC[atom:
ATOM]
RETURNS[stop:
BOOLEAN]]
RETURNS[
ATOM] =
TRUSTED
{
RETURN[AtomsPrivate.EnumerateAtoms[callee: proc]];
}; -- of FindAtom