src/Tools/Metis/src/Subst.sml
changeset 39353 7f11d833d65b
parent 23510 4521fead5609
parent 39349 2d0a4361c3ef
child 39443 e330437cd22a
equal deleted inserted replaced
39313:41ce0b56d858 39353:7f11d833d65b
     1 (* ========================================================================= *)
     1 (* ========================================================================= *)
     2 (* FIRST ORDER LOGIC SUBSTITUTIONS                                           *)
     2 (* FIRST ORDER LOGIC SUBSTITUTIONS                                           *)
     3 (* Copyright (c) 2002-2006 Joe Hurd, distributed under the BSD License *)
     3 (* Copyright (c) 2002-2006 Joe Hurd, distributed under the BSD License       *)
     4 (* ========================================================================= *)
     4 (* ========================================================================= *)
     5 
     5 
     6 structure Subst :> Subst =
     6 structure Subst :> Subst =
     7 struct
     7 struct
     8 
     8 
    28 
    28 
    29 fun insert (Subst m) v_tm = Subst (NameMap.insert m v_tm);
    29 fun insert (Subst m) v_tm = Subst (NameMap.insert m v_tm);
    30 
    30 
    31 fun singleton v_tm = insert empty v_tm;
    31 fun singleton v_tm = insert empty v_tm;
    32 
    32 
    33 local
       
    34   fun compatible (tm1,tm2) =
       
    35       if tm1 = tm2 then SOME tm1 else raise Error "Subst.union: incompatible";
       
    36 in
       
    37   fun union (s1 as Subst m1) (s2 as Subst m2) =
       
    38       if NameMap.null m1 then s2
       
    39       else if NameMap.null m2 then s1
       
    40       else Subst (NameMap.union compatible m1 m2);
       
    41 end;
       
    42 
       
    43 fun toList (Subst m) = NameMap.toList m;
    33 fun toList (Subst m) = NameMap.toList m;
    44 
    34 
    45 fun fromList l = Subst (NameMap.fromList l);
    35 fun fromList l = Subst (NameMap.fromList l);
    46 
    36 
    47 fun foldl f b (Subst m) = NameMap.foldl f b m;
    37 fun foldl f b (Subst m) = NameMap.foldl f b m;
    48 
    38 
    49 fun foldr f b (Subst m) = NameMap.foldr f b m;
    39 fun foldr f b (Subst m) = NameMap.foldr f b m;
    50 
    40 
    51 fun pp ppstrm sub =
    41 fun pp sub =
    52     Parser.ppBracket "<[" "]>"
    42     Print.ppBracket "<[" "]>"
    53       (Parser.ppSequence "," (Parser.ppBinop " |->" Parser.ppString Term.pp))
    43       (Print.ppOpList "," (Print.ppOp2 " |->" Name.pp Term.pp))
    54       ppstrm (toList sub);
    44       (toList sub);
    55 
    45 
    56 val toString = Parser.toString pp;
    46 val toString = Print.toString pp;
    57 
    47 
    58 (* ------------------------------------------------------------------------- *)
    48 (* ------------------------------------------------------------------------- *)
    59 (* Normalizing removes identity substitutions.                               *)
    49 (* Normalizing removes identity substitutions.                               *)
    60 (* ------------------------------------------------------------------------- *)
    50 (* ------------------------------------------------------------------------- *)
    61 
    51 
    76 
    66 
    77 fun subst sub =
    67 fun subst sub =
    78     let
    68     let
    79       fun tmSub (tm as Term.Var v) =
    69       fun tmSub (tm as Term.Var v) =
    80           (case peek sub v of
    70           (case peek sub v of
    81              SOME tm' => if Sharing.pointerEqual (tm,tm') then tm else tm'
    71              SOME tm' => if Portable.pointerEqual (tm,tm') then tm else tm'
    82            | NONE => tm)
    72            | NONE => tm)
    83         | tmSub (tm as Term.Fn (f,args)) =
    73         | tmSub (tm as Term.Fn (f,args)) =
    84           let
    74           let
    85             val args' = Sharing.map tmSub args
    75             val args' = Sharing.map tmSub args
    86           in
    76           in
    87             if Sharing.pointerEqual (args,args') then tm
    77             if Portable.pointerEqual (args,args') then tm
    88             else Term.Fn (f,args')
    78             else Term.Fn (f,args')
    89           end
    79           end
    90     in
    80     in
    91       fn tm => if null sub then tm else tmSub tm
    81       fn tm => if null sub then tm else tmSub tm
    92     end;
    82     end;
   125     in
   115     in
   126       if null sub2 then sub1 else NameMap.foldl f sub2 m1
   116       if null sub2 then sub1 else NameMap.foldl f sub2 m1
   127     end;
   117     end;
   128 
   118 
   129 (* ------------------------------------------------------------------------- *)
   119 (* ------------------------------------------------------------------------- *)
   130 (* Substitutions can be inverted iff they are renaming substitutions.        *) 
   120 (* Creating the union of two compatible substitutions.                       *)
       
   121 (* ------------------------------------------------------------------------- *)
       
   122 
       
   123 local
       
   124   fun compatible ((_,tm1),(_,tm2)) =
       
   125       if Term.equal tm1 tm2 then SOME tm1
       
   126       else raise Error "Subst.union: incompatible";
       
   127 in
       
   128   fun union (s1 as Subst m1) (s2 as Subst m2) =
       
   129       if NameMap.null m1 then s2
       
   130       else if NameMap.null m2 then s1
       
   131       else Subst (NameMap.union compatible m1 m2);
       
   132 end;
       
   133 
       
   134 (* ------------------------------------------------------------------------- *)
       
   135 (* Substitutions can be inverted iff they are renaming substitutions.        *)
   131 (* ------------------------------------------------------------------------- *)
   136 (* ------------------------------------------------------------------------- *)
   132 
   137 
   133 local
   138 local
   134   fun inv (v, Term.Var w, s) =
   139   fun inv (v, Term.Var w, s) =
   135       if NameMap.inDomain w s then raise Error "Subst.invert: non-injective"
   140       if NameMap.inDomain w s then raise Error "Subst.invert: non-injective"
   148 val freshVars =
   153 val freshVars =
   149     let
   154     let
   150       fun add (v,m) = insert m (v, Term.newVar ())
   155       fun add (v,m) = insert m (v, Term.newVar ())
   151     in
   156     in
   152       NameSet.foldl add empty
   157       NameSet.foldl add empty
       
   158     end;
       
   159 
       
   160 (* ------------------------------------------------------------------------- *)
       
   161 (* Free variables.                                                           *)
       
   162 (* ------------------------------------------------------------------------- *)
       
   163 
       
   164 val redexes =
       
   165     let
       
   166       fun add (v,_,s) = NameSet.add s v
       
   167     in
       
   168       foldl add NameSet.empty
       
   169     end;
       
   170 
       
   171 val residueFreeVars =
       
   172     let
       
   173       fun add (_,t,s) = NameSet.union s (Term.freeVars t)
       
   174     in
       
   175       foldl add NameSet.empty
       
   176     end;
       
   177 
       
   178 val freeVars =
       
   179     let
       
   180       fun add (v,t,s) = NameSet.union (NameSet.add s v) (Term.freeVars t)
       
   181     in
       
   182       foldl add NameSet.empty
       
   183     end;
       
   184 
       
   185 (* ------------------------------------------------------------------------- *)
       
   186 (* Functions.                                                                *)
       
   187 (* ------------------------------------------------------------------------- *)
       
   188 
       
   189 val functions =
       
   190     let
       
   191       fun add (_,t,s) = NameAritySet.union s (Term.functions t)
       
   192     in
       
   193       foldl add NameAritySet.empty
   153     end;
   194     end;
   154 
   195 
   155 (* ------------------------------------------------------------------------- *)
   196 (* ------------------------------------------------------------------------- *)
   156 (* Matching for first order logic terms.                                     *)
   197 (* Matching for first order logic terms.                                     *)
   157 (* ------------------------------------------------------------------------- *)
   198 (* ------------------------------------------------------------------------- *)
   162       let
   203       let
   163         val sub =
   204         val sub =
   164             case peek sub v of
   205             case peek sub v of
   165               NONE => insert sub (v,tm)
   206               NONE => insert sub (v,tm)
   166             | SOME tm' =>
   207             | SOME tm' =>
   167               if tm = tm' then sub
   208               if Term.equal tm tm' then sub
   168               else raise Error "Subst.match: incompatible matches"
   209               else raise Error "Subst.match: incompatible matches"
   169       in
   210       in
   170         matchList sub rest
   211         matchList sub rest
   171       end
   212       end
   172     | matchList sub ((Term.Fn (f1,args1), Term.Fn (f2,args2)) :: rest) =
   213     | matchList sub ((Term.Fn (f1,args1), Term.Fn (f2,args2)) :: rest) =
   173       if f1 = f2 andalso length args1 = length args2 then
   214       if Name.equal f1 f2 andalso length args1 = length args2 then
   174         matchList sub (zip args1 args2 @ rest)
   215         matchList sub (zip args1 args2 @ rest)
   175       else raise Error "Subst.match: different structure"
   216       else raise Error "Subst.match: different structure"
   176     | matchList _ _ = raise Error "Subst.match: functions can't match vars";
   217     | matchList _ _ = raise Error "Subst.match: functions can't match vars";
   177 in
   218 in
   178   fun match sub tm1 tm2 = matchList sub [(tm1,tm2)];
   219   fun match sub tm1 tm2 = matchList sub [(tm1,tm2)];
   195         (case peek sub v of
   236         (case peek sub v of
   196            NONE => solve (compose sub (singleton (v,tm))) rest
   237            NONE => solve (compose sub (singleton (v,tm))) rest
   197          | SOME tm' => solve' sub tm' tm rest)
   238          | SOME tm' => solve' sub tm' tm rest)
   198     | solve' sub tm1 (tm2 as Term.Var _) rest = solve' sub tm2 tm1 rest
   239     | solve' sub tm1 (tm2 as Term.Var _) rest = solve' sub tm2 tm1 rest
   199     | solve' sub (Term.Fn (f1,args1)) (Term.Fn (f2,args2)) rest =
   240     | solve' sub (Term.Fn (f1,args1)) (Term.Fn (f2,args2)) rest =
   200       if f1 = f2 andalso length args1 = length args2 then
   241       if Name.equal f1 f2 andalso length args1 = length args2 then
   201         solve sub (zip args1 args2 @ rest)
   242         solve sub (zip args1 args2 @ rest)
   202       else
   243       else
   203         raise Error "Subst.unify: different structure";
   244         raise Error "Subst.unify: different structure";
   204 in
   245 in
   205   fun unify sub tm1 tm2 = solve sub [(tm1,tm2)];
   246   fun unify sub tm1 tm2 = solve sub [(tm1,tm2)];