<> <> <> DIRECTORY Atom USING[GetPName], FileUtilDefs USING[UpperCase], MCrossRefDefs, MCrossSorter, Rope USING[ROPE, Size, Fetch]; MCrossSorterImpl: PROGRAM IMPORTS Atom, FileUtilDefs, Rope EXPORTS MCrossSorter = BEGIN OPEN FileUtilDefs, MCrossSorter, MCrossRefDefs; <> NotInitialized: PUBLIC ERROR = CODE; <> SortTableLength: CARDINAL = 256; <> SortTable: TYPE = REF ASortTable; ASortTable: TYPE = ARRAY SortTableIndex OF RECORD[first, last: TokenHandle]; SortTableIndex: TYPE = [0..SortTableLength); <> sortTables: ARRAY [0..1] OF SortTable _ [NIL, NIL]; lastKeyIndex: CARDINAL _ 0; initialized: BOOLEAN _ FALSE; <> Initialize: PUBLIC PROC[keyLength: CARDINAL] = { Clear[]; IF initialized THEN { sortTables[0] _ NIL; sortTables[1] _ NIL}; IF keyLength = 0 THEN keyLength _ 1; lastKeyIndex _ keyLength - 1; sortTables _ [NEW[ASortTable], NEW[ASortTable]]; sortTables[0]^ _ ALL[[NIL, NIL]]; sortTables[1]^ _ ALL[[NIL, NIL]]; initialized _ TRUE; }; Finalize: PUBLIC PROC = { Clear[]; IF initialized THEN { sortTables[0] _ NIL; sortTables[1] _ NIL; initialized _ FALSE}; }; Clear: PUBLIC PROC = { i: SortTableIndex; k: [0..1]; IF ~initialized THEN RETURN; FOR k IN [0..1] DO FOR i IN SortTableIndex DO sortTables[k][i] _ [NIL, NIL]; ENDLOOP; ENDLOOP; }; Enter: PUBLIC PROC[token: TokenHandle] = { Insert[sortTables[lastKeyIndex MOD 2], token, GetSTI[Atom.GetPName[token.name], lastKeyIndex]]; }; Enumerate: PUBLIC PROC[leafProc: PROC[token: TokenHandle] RETURNS[stop: BOOLEAN], order: SortOrder _ unordered] RETURNS[stopped: BOOLEAN] = { i: SortTableIndex; st: SortTable = sortTables[0]; IF ~initialized THEN ERROR NotInitialized; IF order # unordered THEN Sort[]; IF order = decreasing THEN FOR i DECREASING IN SortTableIndex DO leaf: TokenHandle; st[i].first _ ReverseEntryList[st[i].first]; FOR leaf _ st[i].first, leaf.next UNTIL leaf = NIL DO IF leafProc[leaf] THEN { st[i].first _ ReverseEntryList[st[i].first]; RETURN[TRUE]}; ENDLOOP; st[i].first _ ReverseEntryList[st[i].first]; -- otherwise can't enumerate again ENDLOOP ELSE FOR i IN SortTableIndex DO leaf: TokenHandle; FOR leaf _ st[i].first, leaf.next UNTIL leaf = NIL DO IF leafProc[leaf] THEN RETURN[TRUE]; ENDLOOP; ENDLOOP; RETURN[FALSE]; }; <> GetSTI: PROC[key: Rope.ROPE, chi: CARDINAL] RETURNS[SortTableIndex]= INLINE { IF Rope.Size[key] <= chi THEN RETURN[FIRST[SortTableIndex]]; RETURN[LOOPHOLE[UpperCase[Rope.Fetch[key, chi]]]]}; ReverseEntryList: PROC[this: TokenHandle] RETURNS[last: TokenHandle _ NIL] = INLINE { UNTIL this = NIL DO next: TokenHandle _ this.next; this.next _ last; last _ this; this _ next; ENDLOOP}; Sort: PROC = { FOR k: CARDINAL DECREASING IN [0..lastKeyIndex) DO oldST: SortTable = sortTables[(k+1) MOD 2]; newST: SortTable = sortTables[k MOD 2]; FOR i: SortTableIndex IN SortTableIndex DO entry: TokenHandle _ oldST[i].first; oldST[i] _ [NIL, NIL]; UNTIL entry = NIL DO next: TokenHandle = entry.next; Insert[newST, entry, GetSTI[Atom.GetPName[entry.name], k]]; entry _ next; ENDLOOP; ENDLOOP; ENDLOOP; }; Insert: PROC[st: SortTable, entry: TokenHandle, sti: SortTableIndex] = INLINE { IF st[sti].first = NIL THEN st[sti].first _ entry ELSE st[sti].last.next _ entry; st[sti].last _ entry; entry.next _ NIL}; END.