
% A simple symbol table, with support for generation of ``temporary''
% names.

% Many of these predicates could be merged (see Sterling and Shapiro for
% some approaches to implementing ``dictionaries'' in Prolog).  I've
% deliberately avoided being very ``clever''.

% Also a couple of the predicates aren't really useful.  I've just
% included them for completeness.


% initTab(SymTab)
%
%   Argument is a symbol table in its initial state.

initTab(tab(0, [])).


% empty(SymTab)
%
%   Argument is an empty symbol table.

emptyTab(tab(_, [])).


% addKey(SymTab, Key, Data, NewSymTab).
%
%   Add record with specified key to symbol table.

addKey(tab(_, L), Key, _, _) :-
  member(rec(Key, _), L),
  !,
  printString("Key "), write(Key), printString(" already in table."),
  fail.

addKey(tab(C, L), Key, Data, tab(C, [rec(Key, Data) | L])).

% remKey(SymbTab, Key, Data, NewSymTab).
%
%   Remove record with specified key from symbol table.

remKey(tab(C, L), Key, Data, tab(C, M)) :- remove(rec(Key, Data), L, M).

% getKey(SymTab, Key, Data).
%
%   Return value of record with specified key from symbol table.

getKey(tab(_, L), Key, Data) :- member(rec(Key, Data), L).


% REMARK: it would probably be a useful extension to allow specification
% of a prefix for the keys returned by the following predicates.


% addAny(SymTab, Key, Data, NewSymTab).
%
%   Add record with unspecified key to symbol table.  `Key' is instantiated
%   to a new symbol.

addAny(tab(C, L), Key, Data, tab(D, [rec(Key, Data) | L])) :-
  newKey(C, L, D, Key).

newKey(C, L, E, Key) :-
  name(C, Str),
  name(New, [116 | Str]),
  D is C + 1,
  ((member(rec(New, _), L), !, newKey(D, L, E, Key)) ;
   (E = D, Key = New)).

% remAny(SymTab, Key, Data, NewSymTab).
%
%   Remove record with unspecified key from symbol table.  `Key' is
%   instantiated to the key of the record removed.

remAny(SymTab, Key, Data, NewSymTab) :- remKey(SymTab, Key, Data, NewSymTab).

% getAny(SymTab, Key, Data).
%
%   Return value of record with specified key from symbol table.  `Key' is
%   instantiated to the key of the record removed.

getAny(SymTab, Key, Data) :- getKey(SymTab, Key, Data).

