src/Tools/Metis/src/Atom.sml
changeset 39348 6f9c9899f99f
child 39349 2d0a4361c3ef
equal deleted inserted replaced
39347:50dec19e682b 39348:6f9c9899f99f
       
     1 (* ========================================================================= *)
       
     2 (* FIRST ORDER LOGIC ATOMS                                                   *)
       
     3 (* Copyright (c) 2001-2006 Joe Hurd, distributed under the GNU GPL version 2 *)
       
     4 (* ========================================================================= *)
       
     5 
       
     6 structure Atom :> Atom =
       
     7 struct
       
     8 
       
     9 open Useful;
       
    10 
       
    11 (* ------------------------------------------------------------------------- *)
       
    12 (* A type for storing first order logic atoms.                               *)
       
    13 (* ------------------------------------------------------------------------- *)
       
    14 
       
    15 type relationName = Name.name;
       
    16 
       
    17 type relation = relationName * int;
       
    18 
       
    19 type atom = relationName * Term.term list;
       
    20 
       
    21 (* ------------------------------------------------------------------------- *)
       
    22 (* Constructors and destructors.                                             *)
       
    23 (* ------------------------------------------------------------------------- *)
       
    24 
       
    25 fun name ((rel,_) : atom) = rel;
       
    26 
       
    27 fun arguments ((_,args) : atom) = args;
       
    28 
       
    29 fun arity atm = length (arguments atm);
       
    30 
       
    31 fun relation atm = (name atm, arity atm);
       
    32 
       
    33 val functions =
       
    34     let
       
    35       fun f (tm,acc) = NameAritySet.union (Term.functions tm) acc
       
    36     in
       
    37       fn atm => foldl f NameAritySet.empty (arguments atm)
       
    38     end;
       
    39 
       
    40 val functionNames =
       
    41     let
       
    42       fun f (tm,acc) = NameSet.union (Term.functionNames tm) acc
       
    43     in
       
    44       fn atm => foldl f NameSet.empty (arguments atm)
       
    45     end;
       
    46 
       
    47 (* Binary relations *)
       
    48 
       
    49 fun mkBinop p (a,b) : atom = (p,[a,b]);
       
    50 
       
    51 fun destBinop p (x,[a,b]) =
       
    52     if Name.equal x p then (a,b) else raise Error "Atom.destBinop: wrong binop"
       
    53   | destBinop _ _ = raise Error "Atom.destBinop: not a binop";
       
    54 
       
    55 fun isBinop p = can (destBinop p);
       
    56 
       
    57 (* ------------------------------------------------------------------------- *)
       
    58 (* The size of an atom in symbols.                                           *)
       
    59 (* ------------------------------------------------------------------------- *)
       
    60 
       
    61 fun symbols atm = foldl (fn (tm,z) => Term.symbols tm + z) 1 (arguments atm);
       
    62 
       
    63 (* ------------------------------------------------------------------------- *)
       
    64 (* A total comparison function for atoms.                                    *)
       
    65 (* ------------------------------------------------------------------------- *)
       
    66 
       
    67 fun compare ((p1,tms1),(p2,tms2)) =
       
    68     case Name.compare (p1,p2) of
       
    69       LESS => LESS
       
    70     | EQUAL => lexCompare Term.compare (tms1,tms2)
       
    71     | GREATER => GREATER;
       
    72 
       
    73 fun equal atm1 atm2 = compare (atm1,atm2) = EQUAL;
       
    74 
       
    75 (* ------------------------------------------------------------------------- *)
       
    76 (* Subterms.                                                                 *)
       
    77 (* ------------------------------------------------------------------------- *)
       
    78 
       
    79 fun subterm _ [] = raise Bug "Atom.subterm: empty path"
       
    80   | subterm ((_,tms) : atom) (h :: t) =
       
    81     if h >= length tms then raise Error "Atom.subterm: bad path"
       
    82     else Term.subterm (List.nth (tms,h)) t;
       
    83 
       
    84 fun subterms ((_,tms) : atom) =
       
    85     let
       
    86       fun f ((n,tm),l) = map (fn (p,s) => (n :: p, s)) (Term.subterms tm) @ l
       
    87     in
       
    88       foldl f [] (enumerate tms)
       
    89     end;
       
    90 
       
    91 fun replace _ ([],_) = raise Bug "Atom.replace: empty path"
       
    92   | replace (atm as (rel,tms)) (h :: t, res) : atom =
       
    93     if h >= length tms then raise Error "Atom.replace: bad path"
       
    94     else
       
    95       let
       
    96         val tm = List.nth (tms,h)
       
    97         val tm' = Term.replace tm (t,res)
       
    98       in
       
    99         if Portable.pointerEqual (tm,tm') then atm
       
   100         else (rel, updateNth (h,tm') tms)
       
   101       end;
       
   102 
       
   103 fun find pred =
       
   104     let
       
   105       fun f (i,tm) =
       
   106           case Term.find pred tm of
       
   107             SOME path => SOME (i :: path)
       
   108           | NONE => NONE
       
   109     in
       
   110       fn (_,tms) : atom => first f (enumerate tms)
       
   111     end;
       
   112 
       
   113 (* ------------------------------------------------------------------------- *)
       
   114 (* Free variables.                                                           *)
       
   115 (* ------------------------------------------------------------------------- *)
       
   116 
       
   117 fun freeIn v atm = List.exists (Term.freeIn v) (arguments atm);
       
   118 
       
   119 val freeVars =
       
   120     let
       
   121       fun f (tm,acc) = NameSet.union (Term.freeVars tm) acc
       
   122     in
       
   123       fn atm => foldl f NameSet.empty (arguments atm)
       
   124     end;
       
   125 
       
   126 (* ------------------------------------------------------------------------- *)
       
   127 (* Substitutions.                                                            *)
       
   128 (* ------------------------------------------------------------------------- *)
       
   129 
       
   130 fun subst sub (atm as (p,tms)) : atom =
       
   131     let
       
   132       val tms' = Sharing.map (Subst.subst sub) tms
       
   133     in
       
   134       if Portable.pointerEqual (tms',tms) then atm else (p,tms')
       
   135     end;
       
   136 
       
   137 (* ------------------------------------------------------------------------- *)
       
   138 (* Matching.                                                                 *)
       
   139 (* ------------------------------------------------------------------------- *)
       
   140 
       
   141 local
       
   142   fun matchArg ((tm1,tm2),sub) = Subst.match sub tm1 tm2;
       
   143 in
       
   144   fun match sub (p1,tms1) (p2,tms2) =
       
   145       let
       
   146         val _ = (Name.equal p1 p2 andalso length tms1 = length tms2) orelse
       
   147                 raise Error "Atom.match"
       
   148       in
       
   149         foldl matchArg sub (zip tms1 tms2)
       
   150       end;
       
   151 end;
       
   152 
       
   153 (* ------------------------------------------------------------------------- *)
       
   154 (* Unification.                                                              *)
       
   155 (* ------------------------------------------------------------------------- *)
       
   156 
       
   157 local
       
   158   fun unifyArg ((tm1,tm2),sub) = Subst.unify sub tm1 tm2;
       
   159 in
       
   160   fun unify sub (p1,tms1) (p2,tms2) =
       
   161       let
       
   162         val _ = (Name.equal p1 p2 andalso length tms1 = length tms2) orelse
       
   163                 raise Error "Atom.unify"
       
   164       in
       
   165         foldl unifyArg sub (zip tms1 tms2)
       
   166       end;
       
   167 end;
       
   168 
       
   169 (* ------------------------------------------------------------------------- *)
       
   170 (* The equality relation.                                                    *)
       
   171 (* ------------------------------------------------------------------------- *)
       
   172 
       
   173 val eqRelationName = Name.fromString "=";
       
   174 
       
   175 val eqRelationArity = 2;
       
   176 
       
   177 val eqRelation = (eqRelationName,eqRelationArity);
       
   178 
       
   179 val mkEq = mkBinop eqRelationName;
       
   180 
       
   181 fun destEq x = destBinop eqRelationName x;
       
   182 
       
   183 fun isEq x = isBinop eqRelationName x;
       
   184 
       
   185 fun mkRefl tm = mkEq (tm,tm);
       
   186 
       
   187 fun destRefl atm =
       
   188     let
       
   189       val (l,r) = destEq atm
       
   190       val _ = Term.equal l r orelse raise Error "Atom.destRefl"
       
   191     in
       
   192       l
       
   193     end;
       
   194 
       
   195 fun isRefl x = can destRefl x;
       
   196 
       
   197 fun sym atm =
       
   198     let
       
   199       val (l,r) = destEq atm
       
   200       val _ = not (Term.equal l r) orelse raise Error "Atom.sym: refl"
       
   201     in
       
   202       mkEq (r,l)
       
   203     end;
       
   204 
       
   205 fun lhs atm = fst (destEq atm);
       
   206 
       
   207 fun rhs atm = snd (destEq atm);
       
   208 
       
   209 (* ------------------------------------------------------------------------- *)
       
   210 (* Special support for terms with type annotations.                          *)
       
   211 (* ------------------------------------------------------------------------- *)
       
   212 
       
   213 fun typedSymbols ((_,tms) : atom) =
       
   214     foldl (fn (tm,z) => Term.typedSymbols tm + z) 1 tms;
       
   215 
       
   216 fun nonVarTypedSubterms (_,tms) =
       
   217     let
       
   218       fun addArg ((n,arg),acc) =
       
   219           let
       
   220             fun addTm ((path,tm),acc) = (n :: path, tm) :: acc
       
   221           in
       
   222             foldl addTm acc (Term.nonVarTypedSubterms arg)
       
   223           end
       
   224     in
       
   225       foldl addArg [] (enumerate tms)
       
   226     end;
       
   227 
       
   228 (* ------------------------------------------------------------------------- *)
       
   229 (* Parsing and pretty printing.                                              *)
       
   230 (* ------------------------------------------------------------------------- *)
       
   231 
       
   232 val pp = Print.ppMap Term.Fn Term.pp;
       
   233 
       
   234 val toString = Print.toString pp;
       
   235 
       
   236 fun fromString s = Term.destFn (Term.fromString s);
       
   237 
       
   238 val parse = Parse.parseQuotation Term.toString fromString;
       
   239 
       
   240 end
       
   241 
       
   242 structure AtomOrdered =
       
   243 struct type t = Atom.atom val compare = Atom.compare end
       
   244 
       
   245 structure AtomMap = KeyMap (AtomOrdered);
       
   246 
       
   247 structure AtomSet = ElementSet (AtomMap);