-- NameSymbolTableImpl.Mesa
-- written by Paxton. June 1981
-- last written by Paxton. September 22, 1982 2:38 pm
Last Edited by: Maxwell, January 5, 1983 12:34 pm
DIRECTORY
NameSymbolTable,
JaMBasic,
JaMOps,
Atom,
Rope;
NameSymbolTableImpl: CEDAR MONITOR
IMPORTS JaMOps, Atom, Rope
EXPORTS NameSymbolTable =
BEGIN OPEN NameSymbolTable;
-- ***** Names
MakeNameFromRope: PUBLIC PROC [rope: Rope.ROPE] RETURNS [Name] = TRUSTED {
RETURN [MakeName[LOOPHOLE[Rope.Flatten[rope], REF READONLY TEXT]]] };
MakeName: PUBLIC PROC [text: REF READONLY TEXT] RETURNS [Name] = TRUSTED {
obj: name JaMBasic.Object;
known: BOOLEAN;
IF text=NIL OR text.length=0 THEN RETURN [nullName];
[obj,known] ← JaMOps.CreateName[LOOPHOLE[text,LONG STRING]];
RETURN [LOOPHOLE[obj.id]] };
atomText: REF TEXTNEW[TEXT[64]];
AtomFromName: PUBLIC PROC [name: Name] RETURNS [ATOM] = {
RETURN [Atom.MakeAtom[RopeFromName[name]]] };
FromName: PUBLIC PROC [name: Name, text: REF TEXT] = TRUSTED {
nameObj: name JaMBasic.Object ← [L,name[LOOPHOLE[name,JaMBasic.NameID]]];
JaMOps.StringText[JaMOps.NameToString[nameObj],LOOPHOLE[text,LONG STRING]] };
RopeFromName: PUBLIC ENTRY PROC [name: Name] RETURNS [rope: Rope.ROPE] = {
ENABLE UNWIND => NULL;
initloc, loc: CARDINAL;
FindInRopeCache: PROC RETURNS [BOOLEAN] = {
ropeCacheProbes ← ropeCacheProbes+1;
DO -- search cache
SELECT ropeCacheNames[loc] FROM
name => {
rope ← ropeCacheRopes[loc];
ropeCacheHits ← ropeCacheHits+1;
RETURN [TRUE] };
nullName => RETURN [FALSE]; -- this is an unused entry
ENDCASE;
SELECT (loc ← loc+1) FROM
ropeCacheSize => IF (loc ← 0)=initloc THEN RETURN [FALSE];
initloc => RETURN [FALSE];
ENDCASE;
ENDLOOP };
PutInRopeCache: PROC = {
IF ropeCacheCount = ropeCacheMax THEN ClearRopeCache[];
loc ← initloc;
DO -- search cache for place to put the entry
SELECT ropeCacheNames[loc] FROM
name => RETURN; -- already in cache
nullName => EXIT; -- this is an unused entry
ENDCASE;
SELECT (loc ← loc+1) FROM
ropeCacheSize => IF (loc ← 0)=initloc THEN ERROR; -- cache full
initloc => ERROR; -- cache full
ENDCASE;
ENDLOOP;
ropeCacheCount ← ropeCacheCount+1;
ropeCacheNames[loc] ← name;
ropeCacheRopes[loc] ← rope };
IF name=nullName THEN RETURN [NIL];
loc ← initloc ← LOOPHOLE[name,CARDINAL] MOD ropeCacheSize;
IF FindInRopeCache[] THEN RETURN;
FromName[name, atomText];
rope ← Rope.FromRefText[atomText];
PutInRopeCache };
ropeCacheSize: CARDINAL = 64; -- should be a power of 2
ropeCacheMax: CARDINAL = (ropeCacheSize*4)/5; -- don't fill too full
ropeCacheCount: CARDINAL; -- number of entries currently in use
RopeCacheNames: TYPE = ARRAY [0..ropeCacheSize) OF Name;
ropeCacheNames: REF RopeCacheNames ← NEW[RopeCacheNames];
RopeCacheRopes: TYPE = ARRAY [0..ropeCacheSize) OF Rope.ROPE;
ropeCacheRopes: REF RopeCacheRopes ← NEW[RopeCacheRopes];
ropeCacheProbes: LONG INTEGER ← 0;
ropeCacheHits: LONG INTEGER ← 0;
ClearRopeCache: PROC = {
IF ropeCacheCount = 0 THEN RETURN;
ropeCacheCount ← 0;
FOR i: CARDINAL IN [0..ropeCacheSize) DO
ropeCacheNames[i] ← nullName; ENDLOOP;
};
TextOverflow: PUBLIC ERROR = CODE; -- never raised by current implementation
-- ***** Objects
Object: PUBLIC TYPE = ARRAY [0..4) OF UNSPECIFIED;
MakeObject: PUBLIC PROC [text: REF READONLY TEXT] RETURNS [Object] = TRUSTED {
RETURN [LOOPHOLE[JaMOps.MakeString[LOOPHOLE[text,LONG STRING]]]] };
NullObject: PUBLIC PROC RETURNS [Object] = {
null: Object ← [0,0,0,0];
RETURN [null] };
-- ***** Initialization
Start: PUBLIC PROC = {
ropeCacheCount ← 1;
ClearRopeCache;
};
END.