src/Tools/Metis/src/Subst.sml
author blanchet
Mon, 13 Sep 2010 21:24:10 +0200
changeset 39353 7f11d833d65b
parent 23510 4521fead5609
parent 39349 2d0a4361c3ef
child 39443 e330437cd22a
permissions -rw-r--r--
merged
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
(* FIRST ORDER LOGIC SUBSTITUTIONS                                           *)
39349
2d0a4361c3ef change license, with Joe Hurd's permission
blanchet
parents: 39348
diff changeset
     3
(* Copyright (c) 2002-2006 Joe Hurd, distributed under the BSD License       *)
39348
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 Subst :> Subst =
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
open Useful;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    10
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    11
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    12
(* A type of first order logic substitutions.                                *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    13
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    14
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    15
datatype subst = Subst of Term.term NameMap.map;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    16
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    17
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    18
(* Basic operations.                                                         *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    19
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    20
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    21
val empty = Subst (NameMap.new ());
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    22
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    23
fun null (Subst m) = NameMap.null m;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    24
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    25
fun size (Subst m) = NameMap.size m;
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 peek (Subst m) v = NameMap.peek m v;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    28
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    29
fun insert (Subst m) v_tm = Subst (NameMap.insert m v_tm);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    30
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    31
fun singleton v_tm = insert empty v_tm;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    32
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    33
fun toList (Subst m) = NameMap.toList m;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    34
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    35
fun fromList l = Subst (NameMap.fromList l);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    36
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    37
fun foldl f b (Subst m) = NameMap.foldl f b m;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    38
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    39
fun foldr f b (Subst m) = NameMap.foldr f b m;
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 pp sub =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    42
    Print.ppBracket "<[" "]>"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    43
      (Print.ppOpList "," (Print.ppOp2 " |->" Name.pp Term.pp))
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    44
      (toList sub);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    45
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    46
val toString = Print.toString pp;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    47
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    48
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    49
(* Normalizing removes identity substitutions.                               *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    50
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    51
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    52
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    53
  fun isNotId (v,tm) = not (Term.equalVar v tm);
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
  fun normalize (sub as Subst m) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    56
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    57
        val m' = NameMap.filter isNotId m
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    58
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    59
        if NameMap.size m = NameMap.size m' then sub else Subst m'
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    60
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    61
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    62
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    63
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    64
(* Applying a substitution to a first order logic term.                      *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    65
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    66
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    67
fun subst sub =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    68
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    69
      fun tmSub (tm as Term.Var v) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    70
          (case peek sub v of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    71
             SOME tm' => if Portable.pointerEqual (tm,tm') then tm else tm'
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    72
           | NONE => tm)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    73
        | tmSub (tm as Term.Fn (f,args)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    74
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    75
            val args' = Sharing.map tmSub args
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    76
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    77
            if Portable.pointerEqual (args,args') then tm
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    78
            else Term.Fn (f,args')
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    79
          end
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
      fn tm => if null sub then tm else tmSub tm
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    82
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    83
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    84
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    85
(* Restricting a substitution to a given set of variables.                   *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    86
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    87
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    88
fun restrict (sub as Subst m) varSet =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    89
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    90
      fun isRestrictedVar (v,_) = NameSet.member v varSet
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    91
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    92
      val m' = NameMap.filter isRestrictedVar m
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    93
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    94
      if NameMap.size m = NameMap.size m' then sub else Subst m'
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    95
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    96
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    97
fun remove (sub as Subst m) varSet =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    98
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    99
      fun isRestrictedVar (v,_) = not (NameSet.member v varSet)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   100
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   101
      val m' = NameMap.filter isRestrictedVar m
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   102
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   103
      if NameMap.size m = NameMap.size m' then sub else Subst m'
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   104
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   105
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   106
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   107
(* Composing two substitutions so that the following identity holds:         *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   108
(*                                                                           *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   109
(* subst (compose sub1 sub2) tm = subst sub2 (subst sub1 tm)                 *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   110
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   111
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   112
fun compose (sub1 as Subst m1) sub2 =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   113
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   114
      fun f (v,tm,s) = insert s (v, subst sub2 tm)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   115
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   116
      if null sub2 then sub1 else NameMap.foldl f sub2 m1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   117
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   118
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   119
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   120
(* Creating the union of two compatible substitutions.                       *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   121
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   122
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   123
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   124
  fun compatible ((_,tm1),(_,tm2)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   125
      if Term.equal tm1 tm2 then SOME tm1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   126
      else raise Error "Subst.union: incompatible";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   127
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   128
  fun union (s1 as Subst m1) (s2 as Subst m2) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   129
      if NameMap.null m1 then s2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   130
      else if NameMap.null m2 then s1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   131
      else Subst (NameMap.union compatible m1 m2);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   132
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   133
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   134
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   135
(* Substitutions can be inverted iff they are renaming substitutions.        *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   136
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   137
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   138
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   139
  fun inv (v, Term.Var w, s) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   140
      if NameMap.inDomain w s then raise Error "Subst.invert: non-injective"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   141
      else NameMap.insert s (w, Term.Var v)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   142
    | inv (_, Term.Fn _, _) = raise Error "Subst.invert: non-variable";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   143
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   144
  fun invert (Subst m) = Subst (NameMap.foldl inv (NameMap.new ()) m);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   145
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   146
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   147
val isRenaming = can invert;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   148
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   149
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   150
(* Creating a substitution to freshen variables.                             *)
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
val freshVars =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   154
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   155
      fun add (v,m) = insert m (v, Term.newVar ())
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   156
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   157
      NameSet.foldl add empty
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   158
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   159
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   160
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   161
(* Free variables.                                                           *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   162
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   163
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   164
val redexes =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   165
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   166
      fun add (v,_,s) = NameSet.add s v
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   167
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   168
      foldl add NameSet.empty
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   169
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   170
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   171
val residueFreeVars =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   172
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   173
      fun add (_,t,s) = NameSet.union s (Term.freeVars t)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   174
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   175
      foldl add NameSet.empty
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   176
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   177
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   178
val freeVars =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   179
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   180
      fun add (v,t,s) = NameSet.union (NameSet.add s v) (Term.freeVars t)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   181
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   182
      foldl add NameSet.empty
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   183
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   184
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   185
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   186
(* Functions.                                                                *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   187
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   188
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   189
val functions =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   190
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   191
      fun add (_,t,s) = NameAritySet.union s (Term.functions t)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   192
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   193
      foldl add NameAritySet.empty
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   194
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   195
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   196
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   197
(* Matching for first order logic terms.                                     *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   198
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   199
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   200
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   201
  fun matchList sub [] = sub
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   202
    | matchList sub ((Term.Var v, tm) :: rest) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   203
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   204
        val sub =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   205
            case peek sub v of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   206
              NONE => insert sub (v,tm)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   207
            | SOME tm' =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   208
              if Term.equal tm tm' then sub
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   209
              else raise Error "Subst.match: incompatible matches"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   210
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   211
        matchList sub rest
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   212
      end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   213
    | matchList sub ((Term.Fn (f1,args1), Term.Fn (f2,args2)) :: rest) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   214
      if Name.equal f1 f2 andalso length args1 = length args2 then
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   215
        matchList sub (zip args1 args2 @ rest)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   216
      else raise Error "Subst.match: different structure"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   217
    | matchList _ _ = raise Error "Subst.match: functions can't match vars";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   218
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   219
  fun match sub tm1 tm2 = matchList sub [(tm1,tm2)];
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   220
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   221
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   222
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   223
(* Unification for first order logic terms.                                  *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   224
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   225
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   226
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   227
  fun solve sub [] = sub
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   228
    | solve sub ((tm1_tm2 as (tm1,tm2)) :: rest) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   229
      if Portable.pointerEqual tm1_tm2 then solve sub rest
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   230
      else solve' sub (subst sub tm1) (subst sub tm2) rest
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   231
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   232
  and solve' sub (Term.Var v) tm rest =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   233
      if Term.equalVar v tm then solve sub rest
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   234
      else if Term.freeIn v tm then raise Error "Subst.unify: occurs check"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   235
      else
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   236
        (case peek sub v of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   237
           NONE => solve (compose sub (singleton (v,tm))) rest
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   238
         | SOME tm' => solve' sub tm' tm rest)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   239
    | solve' sub tm1 (tm2 as Term.Var _) rest = solve' sub tm2 tm1 rest
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   240
    | solve' sub (Term.Fn (f1,args1)) (Term.Fn (f2,args2)) rest =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   241
      if Name.equal f1 f2 andalso length args1 = length args2 then
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   242
        solve sub (zip args1 args2 @ rest)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   243
      else
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   244
        raise Error "Subst.unify: different structure";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   245
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   246
  fun unify sub tm1 tm2 = solve sub [(tm1,tm2)];
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   247
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   248
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   249
end