src/Tools/Metis/src/Sharing.sml
author blanchet
Mon, 13 Sep 2010 21:09:43 +0200
changeset 39348 6f9c9899f99f
child 39349 2d0a4361c3ef
permissions -rw-r--r--
new version of the Metis files
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
39348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     1
(* ========================================================================= *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     2
(* PRESERVING SHARING OF ML VALUES                                           *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     3
(* Copyright (c) 2005-2006 Joe Hurd, distributed under the GNU GPL version 2 *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     4
(* ========================================================================= *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     5
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     6
structure Sharing :> Sharing =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     7
struct
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     8
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     9
infix ==
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    10
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    11
val op== = Portable.pointerEqual;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    12
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    13
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    14
(* Option operations.                                                        *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    15
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    16
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    17
fun mapOption f xo =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    18
    case xo of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    19
      SOME x =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    20
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    21
        val y = f x
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    22
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    23
        if x == y then xo else SOME y
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    24
      end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    25
    | NONE => xo;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    26
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    27
fun mapsOption f xo acc =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    28
    case xo of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    29
      SOME x =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    30
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    31
        val (y,acc) = f x acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    32
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    33
        if x == y then (xo,acc) else (SOME y, acc)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    34
      end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    35
    | NONE => (xo,acc);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    36
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    37
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    38
(* List operations.                                                          *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    39
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    40
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    41
fun map f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    42
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    43
      fun m ys ys_xs xs =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    44
          case xs of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    45
            [] => List.revAppend ys_xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    46
          | x :: xs =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    47
            let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    48
              val y = f x
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    49
              val ys = y :: ys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    50
              val ys_xs = if x == y then ys_xs else (ys,xs)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    51
            in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    52
              m ys ys_xs xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    53
            end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    54
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    55
      fn xs => m [] ([],xs) xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    56
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    57
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    58
fun maps f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    59
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    60
      fun m acc ys ys_xs xs =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    61
          case xs of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    62
            [] => (List.revAppend ys_xs, acc)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    63
          | x :: xs =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    64
            let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    65
              val (y,acc) = f x acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    66
              val ys = y :: ys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    67
              val ys_xs = if x == y then ys_xs else (ys,xs)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    68
            in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    69
              m acc ys ys_xs xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    70
            end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    71
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    72
      fn xs => fn acc => m acc [] ([],xs) xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    73
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    74
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    75
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    76
  fun revTails acc xs =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    77
      case xs of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    78
        [] => acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    79
      | x :: xs' => revTails ((x,xs) :: acc) xs';
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    80
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    81
  fun revMap f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    82
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    83
        fun m ys same xxss =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    84
            case xxss of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    85
              [] => ys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    86
            | (x,xs) :: xxss =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    87
              let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    88
                val y = f x
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    89
                val same = same andalso x == y
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    90
                val ys = if same then xs else y :: ys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    91
              in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    92
                m ys same xxss
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    93
              end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    94
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    95
        fn xs => m [] true (revTails [] xs)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    96
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    97
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    98
  fun revMaps f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    99
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   100
        fun m acc ys same xxss =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   101
            case xxss of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   102
              [] => (ys,acc)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   103
            | (x,xs) :: xxss =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   104
              let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   105
                val (y,acc) = f x acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   106
                val same = same andalso x == y
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   107
                val ys = if same then xs else y :: ys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   108
              in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   109
                m acc ys same xxss
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   110
              end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   111
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   112
        fn xs => fn acc => m acc [] true (revTails [] xs)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   113
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   114
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   115
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   116
fun updateNth (n,x) l =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   117
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   118
      val (a,b) = Useful.revDivide l n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   119
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   120
      case b of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   121
        [] => raise Subscript
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   122
      | h :: t => if x == h then l else List.revAppend (a, x :: t)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   123
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   124
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   125
fun setify l =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   126
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   127
      val l' = Useful.setify l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   128
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   129
      if length l' = length l then l else l'
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   130
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   131
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   132
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   133
(* Function caching.                                                         *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   134
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   135
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   136
fun cache cmp f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   137
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   138
      val cache = ref (Map.new cmp)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   139
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   140
      fn a =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   141
         case Map.peek (!cache) a of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   142
           SOME b => b
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   143
         | NONE =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   144
           let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   145
             val b = f a
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   146
             val () = cache := Map.insert (!cache) (a,b)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   147
           in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   148
             b
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   149
           end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   150
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   151
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   152
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   153
(* Hash consing.                                                             *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   154
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   155
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   156
fun hashCons cmp = cache cmp Useful.I;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   157
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   158
end