src/Pure/symtab.ML
author wenzelm
Fri, 19 Aug 1994 15:41:00 +0200
changeset 563 e9bf62651beb
parent 475 bf2f285aa316
child 1415 cef540a0a10e
permissions -rw-r--r--
replaced mapst by map; added find_first;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
     1
(*  Title:      Pure/symtab.ML
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     2
    ID:         $Id$
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
     3
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     4
    Copyright   1989  University of Cambridge
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     5
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
     6
Unbalanced binary trees indexed by strings; no way to delete an entry.
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     7
*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     8
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
     9
signature SYMTAB =
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    10
sig
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    11
  exception DUPLICATE of string
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
    12
  exception DUPS of string list
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    13
  type 'a table
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    14
  val null: 'a table
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    15
  val is_null: 'a table -> bool
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    16
  val lookup: 'a table * string -> 'a option
563
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    17
  val find_first: (string * 'a -> bool) -> 'a table -> (string * 'a) option
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    18
  val update: (string * 'a) * 'a table -> 'a table
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    19
  val update_new: (string * 'a) * 'a table -> 'a table
563
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    20
  val map: ('a -> 'b) -> 'a table -> 'b table
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    21
  val alist_of: 'a table -> (string * 'a) list  (*obsolete*)
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    22
  val balance: 'a table -> 'a table
563
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    23
  val st_of_alist: (string * 'a) list * 'a table -> 'a table  (*obsolete*)
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    24
  val st_of_declist: (string list * 'a) list * 'a table -> 'a table
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
    25
  val make: (string * 'a) list -> 'a table
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
    26
  val dest: 'a table -> (string * 'a) list
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    27
  val extend: ('a * 'a -> bool) -> 'a table * (string * 'a) list -> 'a table
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
    28
  val extend_new: 'a table * (string * 'a) list -> 'a table
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    29
  val merge: ('a * 'a -> bool) -> 'a table * 'a table -> 'a table
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    30
  val lookup_multi: 'a list table * string -> 'a list
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    31
  val make_multi: (string * 'a) list -> 'a list table
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    32
  val dest_multi: 'a list table -> (string * 'a) list
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    33
end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    34
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    35
functor SymtabFun(): SYMTAB =
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    36
struct
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    37
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    38
(*symbol table errors, such as from update_new*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    39
exception DUPLICATE of string;
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
    40
exception DUPS of string list;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    41
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    42
datatype 'a table = Tip | Branch of (string * 'a * 'a table * 'a table);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    43
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    44
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    45
val null = Tip;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    46
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    47
fun is_null Tip = true
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    48
  | is_null _ = false;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    49
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    50
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    51
fun lookup (symtab: 'a table, key: string) : 'a option =
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    52
  let fun look  Tip  = None
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    53
        | look (Branch (key', entry, left, right)) =
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    54
            if      key < key' then look left
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    55
            else if key' < key then look right
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    56
            else  Some entry
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    57
  in look symtab end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    58
475
bf2f285aa316 added function mapst
clasohm
parents: 374
diff changeset
    59
563
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    60
fun find_first _ Tip = None
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    61
  | find_first pred (Branch (key, entry, left, right)) =
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    62
      (case find_first pred left of
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    63
        None =>
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    64
          if pred (key, entry) then Some (key, entry)
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    65
          else find_first pred right
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    66
      | some => some);
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    67
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
    68
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    69
(*update, allows overwriting of an entry*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    70
fun update ((key: string, entry: 'a), symtab : 'a table)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    71
  : 'a table =
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    72
  let fun upd  Tip  = Branch (key, entry, Tip, Tip)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    73
        | upd (Branch(key', entry', left, right)) =
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    74
            if      key < key' then Branch (key', entry', upd left, right)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    75
            else if key' < key then Branch (key', entry', left, upd right)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    76
            else                    Branch (key, entry, left, right)
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    77
  in  upd symtab  end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    78
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    79
(*Like update but fails if key is already defined in table.
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    80
  Allows st_of_alist, etc. to detect multiple definitions*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    81
fun update_new ((key: string, entry: 'a), symtab : 'a table)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    82
  : 'a table =
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    83
  let fun upd Tip = Branch (key, entry, Tip, Tip)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    84
        | upd (Branch(key', entry', left, right)) =
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    85
            if      key < key' then Branch (key', entry', upd left, right)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    86
            else if key' < key then Branch (key', entry', left, upd right)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    87
            else  raise DUPLICATE(key)
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    88
  in  upd symtab  end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    89
475
bf2f285aa316 added function mapst
clasohm
parents: 374
diff changeset
    90
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    91
(*conversion of symbol table to sorted association list*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    92
fun alist_of (symtab : 'a table) : (string * 'a) list =
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    93
  let fun ali (symtab, cont) = case symtab of
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    94
                Tip => cont
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    95
        | Branch (key, entry, left, right) =>
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    96
            ali(left, (key, entry) :: ali(right, cont))
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
    97
  in  ali (symtab, [])  end;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    98
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
    99
val dest = alist_of;
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   100
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   101
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   102
(*Make a balanced tree of the first n members of the sorted alist (sal).
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   103
  Utility for the function balance.*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   104
fun bal_of (sal, 0) = Tip
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   105
  | bal_of (sal, n) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   106
      let val mid = n div 2
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   107
      in  case  drop (mid, sal) of
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   108
            [] => bal_of (sal, mid)   (*should not occur*)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   109
          | ((key, entry):: pairs) =>
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   110
                Branch(key, entry, bal_of(sal, mid), bal_of(pairs, n-mid-1))
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   111
      end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   112
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   113
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   114
fun balance symtab =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   115
  let val sal = alist_of symtab
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   116
  in  bal_of (sal, length sal)  end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   117
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   118
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   119
(*Addition of association list to a symbol table*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   120
fun st_of_alist (al, symtab) =
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   121
  foldr update_new (al, symtab);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   122
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   123
(*A "declaration" associates the same entry with a list of keys;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   124
  does not allow overwriting of an entry*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   125
fun decl_update_new ((keys : string list, entry: 'a), symtab)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   126
  : 'a table =
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   127
  let fun decl (key, symtab) = update_new ((key, entry), symtab)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   128
  in foldr decl (keys, symtab) end;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   129
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   130
(*Addition of a list of declarations to a symbol table*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   131
fun st_of_declist (dl, symtab) =
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   132
  balance (foldr decl_update_new (dl, symtab));
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   133
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   134
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   135
(* make, extend, merge tables *)
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   136
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   137
fun eq_pair eq ((key1, entry1), (key2, entry2)) =
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   138
  key1 = key2 andalso eq (entry1, entry2);
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   139
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   140
fun make alst =
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   141
  (case gen_duplicates eq_fst alst of
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   142
    [] => balance (st_of_alist (alst, Tip))
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   143
  | dups => raise DUPS (map fst dups));
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   144
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   145
fun extend eq (tab, alst) =
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   146
  generic_extend (eq_pair eq) dest make tab alst;
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   147
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   148
val extend_new = extend (K false);
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   149
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   150
fun merge eq (tab1, tab2) =
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   151
  generic_merge (eq_pair eq) dest make tab1 tab2;
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   152
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   153
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   154
(* tables with multiple entries per key *)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   155
(*order of entries with same key is preserved*)
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   156
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   157
fun lookup_multi (tab, key) =
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   158
  (case lookup (tab, key) of
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   159
    Some entries => entries
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   160
  | None => []);
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   161
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   162
fun cons_entry ((key, entry), tab) =
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   163
  update ((key, entry :: lookup_multi (tab, key)), tab);
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   164
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   165
fun make_multi alst =
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   166
  balance (foldr cons_entry (alst, Tip));
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   167
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   168
fun dest_multi tab =
374
caf9a9b7f605 added make, dest, extend_new;
wenzelm
parents: 234
diff changeset
   169
  flat (map (fn (key, entries) => map (pair key) entries) (dest tab));
234
1b3bee8d5d7e minor cleanup;
wenzelm
parents: 0
diff changeset
   170
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   171
563
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
   172
(* map tables *)
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
   173
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
   174
fun map _ Tip = Tip
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
   175
  | map f (Branch (key, entry, left, right)) =
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
   176
      Branch (key, f entry, map f left, map f right);
e9bf62651beb replaced mapst by map;
wenzelm
parents: 475
diff changeset
   177
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   178
end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   179