<> <> <> <> <> <> <> DIRECTORY Atom, NameSymbolTable, Rope, TJaMBasic, TJaMOps; NameSymbolTableImpl: CEDAR MONITOR IMPORTS TJaMOps, 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 TJaMBasic.Object; known: BOOL; IF text=NIL OR text.length=0 THEN RETURN [nullName]; [obj,known] _ TJaMOps.CreateName[LOOPHOLE[text,LONG STRING]]; RETURN [LOOPHOLE[obj.id]]; }; atomText: REF TEXT _ NEW[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 TJaMBasic.Object _ [L,name[LOOPHOLE[name,TJaMBasic.NameID]]]; TJaMOps.StringText[TJaMOps.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 [BOOL] = { 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[TJaMOps.MakeString[LOOPHOLE[text,LONG STRING]]]] }; NullObject: PUBLIC PROC RETURNS [Object] = { null: Object _ [0,0,0,0]; RETURN [null] }; <<***** Initialization>> Start: PROC = { ropeCacheCount _ 1; ClearRopeCache[]; }; Start[]; END.