-- RTTCache.mesa
-- Russ Atkinson, June 24, 1982 3:34 pm

DIRECTORY
  Rope USING [ROPE],
  RTBasic USING [nullType, Type];

RTTCache: CEDAR DEFINITIONS
  = BEGIN OPEN Rope, RTBasic;

  ProcKey: TYPE = PROC ANY RETURNS ANY;
  InvalidIndex: ERROR;

  IntEntry: TYPE = REF IntEntryRep;
  IntEntryRep: TYPE = RECORD
    [next: IntEntry ← NIL,
     valid: BOOL ← FALSE,
     type: Type ← nullType,
     proc: ProcKey ← NIL,
     int: INT ← -1];

  RefEntry: TYPE = REF RefEntryRep;
  RefEntryRep: TYPE = RECORD
    [next: RefEntry ← NIL,
     valid: BOOL ← FALSE,
     type: Type ← nullType,
     proc: ProcKey ← NIL,
     ref: REF ← NIL];

  ComponentMap: TYPE = REF ComponentMapRep;
  ComponentMapRep: TYPE = RECORD
    [filledTypes, filledNames: CARDINAL ← 0,
     comps: SEQUENCE len: CARDINAL OF ComponentEntry];
  ComponentEntry: TYPE = RECORD
    [validType, validName: BOOL ← FALSE,
     type: Type ← nullType,
     name: ROPE ← NIL];
  NullComponentEntry: ComponentEntry = [FALSE, FALSE, nullType, NIL];       

  LookupInt: PROC
      [type: Type, proc: ProcKey] RETURNS [entry: IntEntry];
      -- looks up the entry corresponding to the type and proc
      -- entry.valid => entry.int is OK

  FillIntEntry: PROC
      [entry: IntEntry, value: INT] RETURNS [alreadyFull: BOOL];
      -- fills the entry acquired by LookupInt
      -- will not overwrite an already full entry

  ClearIntEntry: PROC [entry: IntEntry];
    -- atomically invalidates the value in the entry
    -- an invalid entry always has entry.valid = -1
  
  GetInt: PROC [entry: IntEntry] RETURNS [value: INT, valid: BOOL];
    -- atomically retrieves the value in the entry

  LookupRef: PROC
      [type: Type, proc: ProcKey] RETURNS [entry: RefEntry];
      -- looks up the entry corresponding to the type and proc
      -- entry.valid => entry.ref is OK

  FillRefEntry: PROC
      [entry: RefEntry, value: REF] RETURNS [alreadyFull: BOOL];
      -- fills the entry acquired by LookupRef
      -- will not overwrite an already full entry

  ClearRefEntry: PROC [entry: RefEntry];
    -- atomically invalidates the value in the entry
    -- an invalid entry always has entry.ref = NIL

  GetRef: PROC [entry: RefEntry] RETURNS [value: REF, valid: BOOL];
    -- atomically retrieves the value in the entry

  GetStats: PROC
      RETURNS [intProbes, intMisses, intFilled, refProbes, refMisses, refFilled: INT];

  NewComponentMap: PROC [len: NAT] RETURNS [map: ComponentMap];
    -- generates a new (empty) component map of the given size

  FillNameComponent: PROC
      [map: ComponentMap, index: INT, name: ROPE] RETURNS [alreadyFull: BOOL];
    -- fills in a name component in the component map
    -- will not overwrite an already full component  
    -- will ERROR InvalidIndex if index NOT IN [0..map.len)

  FillTypeComponent: PROC
      [map: ComponentMap, index: INT, type: Type] RETURNS [alreadyFull: BOOL];  
    -- fills in a type component in the component map
    -- will not overwrite an already full component  
    -- will ERROR InvalidIndex if index NOT IN [0..map.len)

  GetComponentAtIndex: PROC
    [map: ComponentMap, index: INT] RETURNS [comp: ComponentEntry];
    -- atomically returns the given component entry
    -- will ERROR InvalidIndex if index NOT IN [0..map.len)

  GetComponentForName: PROC
    [map: ComponentMap, name: ROPE, case: BOOL ← TRUE]
    RETURNS [index: INT, comp: ComponentEntry];
    -- atomically returns the given component entry for the given name
    -- IF case = TRUE, then name search is case-sensitive (Rope convention)
    -- will return [-1, NullComponentEntry] if no such name

  END.