src/Pure/term_ord.ML
author wenzelm
Thu Oct 01 23:27:05 2009 +0200 (2009-10-01)
changeset 32843 c8f5a7c8353f
parent 32841 57dcddf81b01
child 35404 de56579ae229
permissions -rw-r--r--
moved cache_conv to src/Pure/conv.ML, use Thm.cterm_cache;
wenzelm@29269
     1
(*  Title:      Pure/term_ord.ML
wenzelm@29269
     2
    Author:     Tobias Nipkow and Makarius, TU Muenchen
wenzelm@29269
     3
wenzelm@29269
     4
Term orderings.
wenzelm@29269
     5
*)
wenzelm@29269
     6
wenzelm@32841
     7
signature BASIC_TERM_ORD =
wenzelm@32841
     8
sig
wenzelm@32841
     9
  structure Vartab: TABLE
wenzelm@32841
    10
  structure Sorttab: TABLE
wenzelm@32841
    11
  structure Typtab: TABLE
wenzelm@32841
    12
  structure Termtab: TABLE
wenzelm@32841
    13
end;
wenzelm@32841
    14
wenzelm@29269
    15
signature TERM_ORD =
wenzelm@29269
    16
sig
wenzelm@32841
    17
  include BASIC_TERM_ORD
wenzelm@29269
    18
  val fast_indexname_ord: indexname * indexname -> order
wenzelm@29269
    19
  val sort_ord: sort * sort -> order
wenzelm@29269
    20
  val typ_ord: typ * typ -> order
wenzelm@29269
    21
  val fast_term_ord: term * term -> order
wenzelm@29269
    22
  val indexname_ord: indexname * indexname -> order
wenzelm@29269
    23
  val tvar_ord: (indexname * sort) * (indexname * sort) -> order
wenzelm@29269
    24
  val var_ord: (indexname * typ) * (indexname * typ) -> order
wenzelm@29269
    25
  val term_ord: term * term -> order
wenzelm@29269
    26
  val hd_ord: term * term -> order
wenzelm@29269
    27
  val termless: term * term -> bool
wenzelm@29269
    28
  val term_lpo: (term -> int) -> term * term -> order
wenzelm@32841
    29
  val term_cache: (term -> 'a) -> term -> 'a
wenzelm@29269
    30
end;
wenzelm@29269
    31
wenzelm@29269
    32
structure TermOrd: TERM_ORD =
wenzelm@29269
    33
struct
wenzelm@29269
    34
wenzelm@29269
    35
(* fast syntactic ordering -- tuned for inequalities *)
wenzelm@29269
    36
wenzelm@29269
    37
fun fast_indexname_ord ((x, i), (y, j)) =
wenzelm@29269
    38
  (case int_ord (i, j) of EQUAL => fast_string_ord (x, y) | ord => ord);
wenzelm@29269
    39
wenzelm@29269
    40
fun sort_ord SS =
wenzelm@29269
    41
  if pointer_eq SS then EQUAL
wenzelm@29269
    42
  else dict_ord fast_string_ord SS;
wenzelm@29269
    43
wenzelm@29269
    44
local
wenzelm@29269
    45
wenzelm@29269
    46
fun cons_nr (TVar _) = 0
wenzelm@29269
    47
  | cons_nr (TFree _) = 1
wenzelm@29269
    48
  | cons_nr (Type _) = 2;
wenzelm@29269
    49
wenzelm@29269
    50
in
wenzelm@29269
    51
wenzelm@29269
    52
fun typ_ord TU =
wenzelm@29269
    53
  if pointer_eq TU then EQUAL
wenzelm@29269
    54
  else
wenzelm@29269
    55
    (case TU of
wenzelm@29269
    56
      (Type (a, Ts), Type (b, Us)) =>
wenzelm@29269
    57
        (case fast_string_ord (a, b) of EQUAL => dict_ord typ_ord (Ts, Us) | ord => ord)
wenzelm@29269
    58
    | (TFree (a, S), TFree (b, S')) =>
wenzelm@29269
    59
        (case fast_string_ord (a, b) of EQUAL => sort_ord (S, S') | ord => ord)
wenzelm@29269
    60
    | (TVar (xi, S), TVar (yj, S')) =>
wenzelm@29269
    61
        (case fast_indexname_ord (xi, yj) of EQUAL => sort_ord (S, S') | ord => ord)
wenzelm@29269
    62
    | (T, U) => int_ord (cons_nr T, cons_nr U));
wenzelm@29269
    63
wenzelm@29269
    64
end;
wenzelm@29269
    65
wenzelm@29269
    66
local
wenzelm@29269
    67
wenzelm@29269
    68
fun cons_nr (Const _) = 0
wenzelm@29269
    69
  | cons_nr (Free _) = 1
wenzelm@29269
    70
  | cons_nr (Var _) = 2
wenzelm@29269
    71
  | cons_nr (Bound _) = 3
wenzelm@29269
    72
  | cons_nr (Abs _) = 4
wenzelm@29269
    73
  | cons_nr (_ $ _) = 5;
wenzelm@29269
    74
wenzelm@29269
    75
fun struct_ord (Abs (_, _, t), Abs (_, _, u)) = struct_ord (t, u)
wenzelm@29269
    76
  | struct_ord (t1 $ t2, u1 $ u2) =
wenzelm@29269
    77
      (case struct_ord (t1, u1) of EQUAL => struct_ord (t2, u2) | ord => ord)
wenzelm@29269
    78
  | struct_ord (t, u) = int_ord (cons_nr t, cons_nr u);
wenzelm@29269
    79
wenzelm@29269
    80
fun atoms_ord (Abs (_, _, t), Abs (_, _, u)) = atoms_ord (t, u)
wenzelm@29269
    81
  | atoms_ord (t1 $ t2, u1 $ u2) =
wenzelm@29269
    82
      (case atoms_ord (t1, u1) of EQUAL => atoms_ord (t2, u2) | ord => ord)
wenzelm@29269
    83
  | atoms_ord (Const (a, _), Const (b, _)) = fast_string_ord (a, b)
wenzelm@29269
    84
  | atoms_ord (Free (x, _), Free (y, _)) = fast_string_ord (x, y)
wenzelm@29269
    85
  | atoms_ord (Var (xi, _), Var (yj, _)) = fast_indexname_ord (xi, yj)
wenzelm@29269
    86
  | atoms_ord (Bound i, Bound j) = int_ord (i, j)
wenzelm@29269
    87
  | atoms_ord _ = sys_error "atoms_ord";
wenzelm@29269
    88
wenzelm@29269
    89
fun types_ord (Abs (_, T, t), Abs (_, U, u)) =
wenzelm@29269
    90
      (case typ_ord (T, U) of EQUAL => types_ord (t, u) | ord => ord)
wenzelm@29269
    91
  | types_ord (t1 $ t2, u1 $ u2) =
wenzelm@29269
    92
      (case types_ord (t1, u1) of EQUAL => types_ord (t2, u2) | ord => ord)
wenzelm@29269
    93
  | types_ord (Const (_, T), Const (_, U)) = typ_ord (T, U)
wenzelm@29269
    94
  | types_ord (Free (_, T), Free (_, U)) = typ_ord (T, U)
wenzelm@29269
    95
  | types_ord (Var (_, T), Var (_, U)) = typ_ord (T, U)
wenzelm@29269
    96
  | types_ord (Bound _, Bound _) = EQUAL
wenzelm@29269
    97
  | types_ord _ = sys_error "types_ord";
wenzelm@29269
    98
wenzelm@29269
    99
in
wenzelm@29269
   100
wenzelm@29269
   101
fun fast_term_ord tu =
wenzelm@29269
   102
  if pointer_eq tu then EQUAL
wenzelm@29269
   103
  else
wenzelm@29269
   104
    (case struct_ord tu of
wenzelm@29269
   105
      EQUAL => (case atoms_ord tu of EQUAL => types_ord tu | ord => ord)
wenzelm@29269
   106
    | ord => ord);
wenzelm@29269
   107
wenzelm@29269
   108
end;
wenzelm@29269
   109
wenzelm@29269
   110
wenzelm@29269
   111
(* term_ord *)
wenzelm@29269
   112
wenzelm@29269
   113
(*a linear well-founded AC-compatible ordering for terms:
wenzelm@29269
   114
  s < t <=> 1. size(s) < size(t) or
wenzelm@29269
   115
            2. size(s) = size(t) and s=f(...) and t=g(...) and f<g or
wenzelm@29269
   116
            3. size(s) = size(t) and s=f(s1..sn) and t=f(t1..tn) and
wenzelm@29269
   117
               (s1..sn) < (t1..tn) (lexicographically)*)
wenzelm@29269
   118
wenzelm@29269
   119
fun indexname_ord ((x, i), (y, j)) =
wenzelm@29269
   120
  (case int_ord (i, j) of EQUAL => string_ord (x, y) | ord => ord);
wenzelm@29269
   121
wenzelm@29269
   122
val tvar_ord = prod_ord indexname_ord sort_ord;
wenzelm@29269
   123
val var_ord = prod_ord indexname_ord typ_ord;
wenzelm@29269
   124
wenzelm@29269
   125
wenzelm@29269
   126
local
wenzelm@29269
   127
wenzelm@29269
   128
fun hd_depth (t $ _, n) = hd_depth (t, n + 1)
wenzelm@29269
   129
  | hd_depth p = p;
wenzelm@29269
   130
wenzelm@29269
   131
fun dest_hd (Const (a, T)) = (((a, 0), T), 0)
wenzelm@29269
   132
  | dest_hd (Free (a, T)) = (((a, 0), T), 1)
wenzelm@29269
   133
  | dest_hd (Var v) = (v, 2)
wenzelm@29269
   134
  | dest_hd (Bound i) = ((("", i), dummyT), 3)
wenzelm@29269
   135
  | dest_hd (Abs (_, T, _)) = ((("", 0), T), 4);
wenzelm@29269
   136
wenzelm@29269
   137
in
wenzelm@29269
   138
wenzelm@29269
   139
fun term_ord tu =
wenzelm@29269
   140
  if pointer_eq tu then EQUAL
wenzelm@29269
   141
  else
wenzelm@29269
   142
    (case tu of
wenzelm@29269
   143
      (Abs (_, T, t), Abs(_, U, u)) =>
wenzelm@29269
   144
        (case term_ord (t, u) of EQUAL => typ_ord (T, U) | ord => ord)
wenzelm@29269
   145
    | (t, u) =>
wenzelm@29269
   146
        (case int_ord (size_of_term t, size_of_term u) of
wenzelm@29269
   147
          EQUAL =>
wenzelm@29269
   148
            (case prod_ord hd_ord int_ord (hd_depth (t, 0), hd_depth (u, 0)) of
wenzelm@29269
   149
              EQUAL => args_ord (t, u) | ord => ord)
wenzelm@29269
   150
        | ord => ord))
wenzelm@29269
   151
and hd_ord (f, g) =
wenzelm@29269
   152
  prod_ord (prod_ord indexname_ord typ_ord) int_ord (dest_hd f, dest_hd g)
wenzelm@29269
   153
and args_ord (f $ t, g $ u) =
wenzelm@29269
   154
      (case args_ord (f, g) of EQUAL => term_ord (t, u) | ord => ord)
wenzelm@29269
   155
  | args_ord _ = EQUAL;
wenzelm@29269
   156
wenzelm@29269
   157
fun termless tu = (term_ord tu = LESS);
wenzelm@29269
   158
wenzelm@29269
   159
end;
wenzelm@29269
   160
wenzelm@29269
   161
wenzelm@29269
   162
(* Lexicographic path order on terms *)
wenzelm@29269
   163
wenzelm@29269
   164
(*
wenzelm@29269
   165
  See Baader & Nipkow, Term rewriting, CUP 1998.
wenzelm@29269
   166
  Without variables.  Const, Var, Bound, Free and Abs are treated all as
wenzelm@29269
   167
  constants.
wenzelm@29269
   168
wenzelm@29269
   169
  f_ord maps terms to integers and serves two purposes:
wenzelm@29269
   170
  - Predicate on constant symbols.  Those that are not recognised by f_ord
wenzelm@29269
   171
    must be mapped to ~1.
wenzelm@29269
   172
  - Order on the recognised symbols.  These must be mapped to distinct
wenzelm@29269
   173
    integers >= 0.
wenzelm@29269
   174
  The argument of f_ord is never an application.
wenzelm@29269
   175
*)
wenzelm@29269
   176
wenzelm@29269
   177
local
wenzelm@29269
   178
wenzelm@29269
   179
fun unrecognized (Const (a, T)) = ((1, ((a, 0), T)), 0)
wenzelm@29269
   180
  | unrecognized (Free (a, T)) = ((1, ((a, 0), T)), 0)
wenzelm@29269
   181
  | unrecognized (Var v) = ((1, v), 1)
wenzelm@29269
   182
  | unrecognized (Bound i) = ((1, (("", i), dummyT)), 2)
wenzelm@29269
   183
  | unrecognized (Abs (_, T, _)) = ((1, (("", 0), T)), 3);
wenzelm@29269
   184
wenzelm@29269
   185
fun dest_hd f_ord t =
wenzelm@29269
   186
  let val ord = f_ord t
wenzelm@29269
   187
  in if ord = ~1 then unrecognized t else ((0, (("", ord), fastype_of t)), 0) end;
wenzelm@29269
   188
wenzelm@29269
   189
fun term_lpo f_ord (s, t) =
wenzelm@29269
   190
  let val (f, ss) = strip_comb s and (g, ts) = strip_comb t in
wenzelm@29269
   191
    if forall (fn si => term_lpo f_ord (si, t) = LESS) ss
wenzelm@29269
   192
    then case hd_ord f_ord (f, g) of
wenzelm@29269
   193
        GREATER =>
wenzelm@29269
   194
          if forall (fn ti => term_lpo f_ord (s, ti) = GREATER) ts
wenzelm@29269
   195
          then GREATER else LESS
wenzelm@29269
   196
      | EQUAL =>
wenzelm@29269
   197
          if forall (fn ti => term_lpo f_ord (s, ti) = GREATER) ts
wenzelm@29269
   198
          then list_ord (term_lpo f_ord) (ss, ts)
wenzelm@29269
   199
          else LESS
wenzelm@29269
   200
      | LESS => LESS
wenzelm@29269
   201
    else GREATER
wenzelm@29269
   202
  end
wenzelm@29269
   203
and hd_ord f_ord (f, g) = case (f, g) of
wenzelm@29269
   204
    (Abs (_, T, t), Abs (_, U, u)) =>
wenzelm@29269
   205
      (case term_lpo f_ord (t, u) of EQUAL => typ_ord (T, U) | ord => ord)
wenzelm@29269
   206
  | (_, _) => prod_ord (prod_ord int_ord
wenzelm@29269
   207
                  (prod_ord indexname_ord typ_ord)) int_ord
wenzelm@29269
   208
                (dest_hd f_ord f, dest_hd f_ord g);
wenzelm@29269
   209
wenzelm@29269
   210
in
wenzelm@29269
   211
val term_lpo = term_lpo
wenzelm@29269
   212
end;
wenzelm@29269
   213
wenzelm@29269
   214
wenzelm@32841
   215
(* tables and caches *)
wenzelm@32841
   216
wenzelm@32841
   217
structure Vartab = Table(type key = indexname val ord = fast_indexname_ord);
wenzelm@32841
   218
structure Sorttab = Table(type key = sort val ord = sort_ord);
wenzelm@32841
   219
structure Typtab = Table(type key = typ val ord = typ_ord);
wenzelm@32841
   220
structure Termtab = Table(type key = term val ord = fast_term_ord);
wenzelm@32841
   221
wenzelm@32841
   222
fun term_cache f = Cache.create Termtab.empty Termtab.lookup Termtab.update f;
wenzelm@32841
   223
wenzelm@29269
   224
end;
wenzelm@29269
   225
wenzelm@32841
   226
structure Basic_Term_Ord: BASIC_TERM_ORD = TermOrd;
wenzelm@32841
   227
open Basic_Term_Ord;
wenzelm@32841
   228