src/Pure/PIDE/xml.ML
changeset 44809 df3626d1066e
parent 44808 05b8997899a2
child 45155 3216d65d8f34
--- a/src/Pure/PIDE/xml.ML	Wed Sep 07 23:08:04 2011 +0200
+++ b/src/Pure/PIDE/xml.ML	Thu Sep 08 00:20:09 2011 +0200
@@ -229,20 +229,45 @@
 end;
 
 
-(** cache for partial sharing (strings only) **)
+(** cache for substructural sharing **)
+
+fun tree_ord tu =
+  if pointer_eq tu then EQUAL
+  else
+    (case tu of
+      (Text _, Elem _) => LESS
+    | (Elem _, Text _) => GREATER
+    | (Text s, Text s') => fast_string_ord (s, s')
+    | (Elem e, Elem e') =>
+        prod_ord
+          (prod_ord fast_string_ord (list_ord (prod_ord fast_string_ord fast_string_ord)))
+          (list_ord tree_ord) (e, e'));
+
+structure Treetab = Table(type key = tree val ord = tree_ord);
 
 fun cache () =
   let
     val strings = Unsynchronized.ref (Symtab.empty: unit Symtab.table);
+    val trees = Unsynchronized.ref (Treetab.empty: unit Treetab.table);
 
     fun string s =
-      (case Symtab.lookup_key (! strings) s of
-        SOME (s', ()) => s'
-      | NONE => (Unsynchronized.change strings (Symtab.update (s, ())); s));
+      if size s <= 1 then s
+      else
+        (case Symtab.lookup_key (! strings) s of
+          SOME (s', ()) => s'
+        | NONE => (Unsynchronized.change strings (Symtab.update (s, ())); s));
 
-    fun tree (Elem ((name, props), body)) =
-          Elem ((string name, map (pairself string) props), map tree body)
-      | tree (Text s) = Text (string s);
+    fun tree t =
+      (case Treetab.lookup_key (! trees) t of
+        SOME (t', ()) => t'
+      | NONE =>
+          let
+            val t' =
+              (case t of
+                Elem ((a, ps), b) => Elem ((string a, map (pairself string) ps), map tree b)
+              | Text s => Text (string s));
+            val _ = Unsynchronized.change trees (Treetab.update (t', ()));
+          in t' end);
   in tree end;