Arbitrarily typed data.
authorwenzelm
Tue, 14 Oct 1997 17:34:21 +0200
changeset 3863 7ebf561cbbb4
parent 3862 6f389875ab33
child 3864 e0ce3d4ec47d
Arbitrarily typed data.
src/Pure/data.ML
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/data.ML	Tue Oct 14 17:34:21 1997 +0200
@@ -0,0 +1,91 @@
+(*  Title:      Pure/data.ML
+    ID:         $Id$
+    Author:     Markus Wenzel, TU Muenchen
+
+Arbitrarily typed data.  Fools the ML type system via exception
+constructors.
+*)
+
+signature DATA =
+sig
+  type T
+  val empty: T
+  val merge: T * T -> T
+  val print: T -> unit
+  val init: T -> string -> exn -> (exn * exn -> exn) -> (string -> exn -> Pretty.T) -> T
+  val get: T -> string -> exn
+  val put: T -> string -> exn -> T
+end;
+
+
+structure Data: DATA =
+struct
+
+(* datatype T *)
+
+datatype T = Data of (*value, merge method, pp method*)
+  (exn * ((exn * exn -> exn) * (string -> exn -> Pretty.T))) Symtab.table;
+
+
+(* errors *)
+
+fun err_msg_merge kind =
+  error_msg ("Error while trying to merge " ^ quote kind ^ " data");
+
+fun err_dup_init kind =
+  error ("Duplicate initialization of " ^ quote kind ^ " data");
+
+fun err_uninit kind =
+  error ("Tried to access uninitialized " ^ quote kind ^ " data");
+
+
+(* operations *)
+
+val empty = Data Symtab.null;
+
+
+fun merge (Data tab1, Data tab2) =
+  let
+    val data1 = Symtab.dest tab1;
+    val data2 = Symtab.dest tab2;
+    val all_data = data1 @ data2;
+    val kinds = distinct (map fst all_data);
+
+   fun entry data kind =
+     (case assoc (data, kind) of
+       None => []
+     | Some x => [(kind, x)]);
+
+    fun merge_entries [x] = x
+      | merge_entries [(kind, (e1, mths as (mrg, _))), (_, (e2, _))] =
+          (kind, (mrg (e1, e2) handle exn => (err_msg_merge kind; raise exn), mths))
+      | merge_entries _ = sys_error "merge_entries";
+
+    val data = map (fn k => merge_entries (entry data1 k @ entry data2 k)) kinds;
+  in Data (Symtab.make data) end;
+
+
+fun print (Data tab) =
+  let fun prnt (kind, (e, (_, prt))) = Pretty.writeln (prt kind e) in
+    seq prnt (Symtab.dest tab)
+  end;
+
+
+fun init (Data tab) kind e mrg prt =
+  Data (Symtab.update_new ((kind, (e, (mrg, prt))), tab))
+    handle Symtab.DUPLICATE _ => err_dup_init kind;
+
+
+fun get (Data tab) kind =
+  (case Symtab.lookup (tab, kind) of
+    Some (e, _) => e
+  | None => err_uninit kind);
+
+
+fun put (Data tab) kind e =
+  (case Symtab.lookup (tab, kind) of
+    Some (_, meths) => Data (Symtab.update ((kind, (e, meths)), tab))
+  | None => err_uninit kind);
+
+
+end;