(* * I've added a few extra functions into the structure Symbol: * * 'newSymbol' creates a new symbol different from all existing ones * 'enterList' inserts a list of entries into a table * * 'lt' and 'gt' are two comparison functions *) signature SYMBOL = sig eqtype symbol = string * int val symbol: string -> symbol val newSymbol: unit -> symbol val name: symbol -> string val eq: symbol * symbol -> bool val lt: symbol * symbol -> bool val gt: symbol * symbol -> bool type 'a table val empty: 'a table val enter: 'a table * symbol * 'a -> 'a table val enterList: 'a table * (symbol * 'a) list -> 'a table val look: 'a table * symbol -> 'a option end structure Symbol :> SYMBOL = struct type symbol = string * int structure H = HashTable exception Symbol val nextsym = ref 0 val sizeHint = 128 val hashtable: (string, int) H.hash_table = H.mkTable (HashString.hashString, op=) (sizeHint,Symbol) fun symbol name = case H.find hashtable name of SOME i => (name, i) | NONE => let val i = !nextsym in nextsym := i+1; H.insert hashtable (name,i); (name, i) end local val count = ref 0 in fun newSymbol () = let val i = !count val _ = (count := i + 1) val name = Int.toString i in symbol name end end fun name (s, _) = s fun eq ((_, n): symbol, (_, n'): symbol): bool = (n = n') fun lt ((_, n): symbol, (_, n'): symbol): bool = (n < n') fun gt ((_, n): symbol, (_, n'): symbol): bool = (n > n') structure Table = IntMapTable(type key = symbol fun getInt (s, n) = n) type 'a table = 'a Table.table val empty = Table.empty val enter = Table.enter val look = Table.look fun enterList (env, kvs) = case kvs of [] => env | (k, v) :: kvs => let val env = enter (env, k, v) in enterList (env, kvs) end end (* end of structure Symbol *)